폴링
고친 사람 github-actions[bot]
폴링은 새것이 생겼는지 묻는 쪽이 되풀이해 확인하는 방식입니다. 상대가 알려 줄 때까지 기다리지 않습니다. 정해진 간격으로 직접 확인하러 갑니다. 상대가 먼저 알려 줄 길이 없을 때 쓰는 가장 단순한 방법입니다.
쉽고 빠른 이해
폴링은 상대에게 「새것 있나」를 정해진 간격으로 되풀이해 묻는 방식입니다. 주문한 빵이 나왔는지 손님이 몇 분마다 카운터에 가서 물어보는 것이 그 일입니다.
상대가 먼저 알려 주려면 나에게 연락할 길이 있어야 합니다. 그 길이 없거나 만들기 번거로우면, 묻는 쪽이 직접 가서 확인하는 수밖에 없습니다.
어떻게 도나:
- 정해진 간격으로 상대에게 지금 상태를 묻습니다
- 바뀐 것이 없으면 아무 일도 하지 않고 다음 차례를 기다립니다
- 바뀐 것이 있으면 그것을 받아 처리합니다
대가는 둘입니다. 하나는 늦음입니다. 바뀐 순간과 알아채는 순간 사이가 최대 한 간격만큼 벌어집니다. 다른 하나는 헛걸음입니다. 물음 대부분은 「없다」를 듣고 끝납니다. 그만큼 양쪽 일감과 네트워크가 헛돕니다.
상세
폴링은 되풀이해 묻는다는 한 가지 뼈대로 여러 무대에서 쓰입니다. 그 되풀이를 누가 시작하는지부터 봅니다.
카운터에 다시 가 보는 일
빵집에서 빵이 나오면 알려 달라고 부탁할 수 없다고 해 봅시다. 궁금한 사람이 할 수 있는 일은 몇 분에 한 번씩 카운터에 가서 나왔는지 물어보는 것뿐입니다.
자주 갈수록 빨리 알아냅니다. 대신 헛걸음이 그만큼 늘어납니다.
묻는 쪽이 먼저 움직인다
폴링에서 움직이는 것은 상태를 가진 쪽이 아니라 그 상태를 묻는 쪽입니다. 묻는 쪽이 「바뀐 것이 있나」를 물어봅니다. 가진 쪽은 물어볼 때만 답합니다. 가진 쪽이 먼저 연락해 오는 방식은 푸시입니다. 폴링은 그 반대편에 섭니다.
가진 쪽이 먼저 알려 주려면 묻는 쪽의 주소를 알아야 합니다. 그리로 연결도 열 수 있어야 합니다. 묻는 쪽이 방화벽 뒤에 있거나 주소가 자주 바뀌면 그 길이 없습니다. 길이 없으면 되풀이해 물어보는 것 말고는 방법이 없습니다. 그래서 폴링은 알림 방식 중에 제일 먼저 놓이는 바닥입니다.
이 이름은 여러 분야에서 같은 뜻으로 쓰입니다. 브라우저가 서버에 몇 초마다 새 글이 있는지 묻는 것도, 감시 도구가 서버마다 찾아가 수치를 걷어 오는 것도, 프로그램이 장치가 준비됐는지 상태 값을 되풀이해 읽는 것도 전부 폴링입니다. 무대는 달라도 되풀이해 묻는다는 뼈대는 같습니다.
한 가지를 가려 둡니다. 한 번 물어보고 답을 기다리는 것은 폴링이 아닙니다. 답을 듣고 끝난 뒤에 또 묻는 것이 정해져 있어야 폴링입니다. 그 되풀이가 이 이름의 뼈대입니다.
한 번의 폴링이 도는 순서
폴링은 한 번으로 끝나지 않고 답이 나올 때까지 같은 왕복을 되풀이합니다. 오래 걸리는 작업 하나가 끝났는지 묻는 경우로 봅니다.
sequenceDiagram
participant A as 묻는 쪽
participant B as 가진 쪽
loop 정해진 간격마다
A->>B: 새것 있나
B-->>A: 없다
end
A->>B: 새것 있나
B-->>A: 있다. 여기 있다
값을 받아 오는 왕복은 마지막 한 번뿐입니다. 그 앞의 왕복은 전부 「없다」를 확인하고 끝납니다. 이 헛도는 왕복의 수가 폴링을 쓰는 값입니다.
코드로 적으면 짧습니다. 작업이 끝났는지 묻습니다. 안 끝났으면 잠깐 잔 뒤 다시 묻습니다.
while True:
job = get_status("job-42") # running
if job.done:
break
sleep(2) # 2초 뒤 다시 묻는다
sleep 에 넘긴 값이 간격입니다. 폴링을 쓰는 사람이 정하는 값은 거의 이것 하나입니다.
간격이 정하는 두 가지
간격 하나가 늦음과 낭비를 동시에 정합니다. 짧게 잡으면 빨리 알아채는 대신 헛도는 왕복이 늡니다. 길게 잡으면 왕복이 줄어드는 대신 늦게 압니다. 어느 쪽이 더 아픈지를 보고 고릅니다.
| 간격을 짧게 | 간격을 길게 | |
|---|---|---|
| 알아채는 늦음 | 작아진다 | 커진다 |
| 헛도는 왕복 | 많아진다 | 적어진다 |
| 상대가 지는 부담 | 커진다 | 작아진다 |
표의 첫 줄에는 셈할 수 있는 상한이 있습니다. 늦음의 상한은 간격 자체입니다. 5초마다 물으면 바뀐 사실을 아무리 늦어도 5초 뒤에는 압니다.
둘째 줄의 부담은 묻는 쪽이 늘어나면 같이 곱해집니다. 장비 천 대가 1초마다 같은 서버에 물으면 그 서버는 초당 천 번의 요청을 받습니다. 아무것도 안 바뀌는 동안에도 그만큼 받습니다. 그래서 가진 쪽은 너무 잦은 물음을 속도 제한으로 잘라 내기도 합니다.
헛도는 왕복을 줄이는 수단
간격만으로는 늦음과 낭비를 둘 다 줄일 수 없습니다. 그래서 되풀이 자체는 남기되 한 왕복의 값을 낮추는 수단들이 붙습니다. 아래 넷은 따로 쓰기도 하고 겹쳐 쓰기도 합니다.
첫째는 답을 늦추는 것입니다. 물음을 받은 쪽이 바뀐 것이 없으면 바뀔 때까지, 또는 정해진 시간까지 답을 쥐고 있습니다. 헛도는 왕복이 줄어듭니다. 알아채는 속도도 빨라집니다. 이 방식이 롱 폴링입니다.
둘째는 간격을 고정하지 않는 것입니다. 「없다」가 이어지면 기다리는 시간을 점점 늘립니다. 뭔가 나오면 다시 짧게 돌아옵니다. 빈 응답이나 실패가 이어질 때 기다림을 배로 늘려 가는 방식을 지수 백오프라고 합니다.
셋째는 답을 작게 만드는 것입니다. 「지난번에 받은 것과 같나」를 묻습니다. 같으면 본문 없이 「그대로다」만 돌려받습니다. 이렇게 바뀌었을 때만 내용을 받는 요청이 조건부 요청입니다. 지난번 것과 이번 것을 맞대 볼 표시는 ETag(Entity Tag, 개체 태그) 같은 값이 맡습니다.
넷째는 마지막으로 본 지점을 들고 가는 것입니다. 「그 뒤로 생긴 것만 주세요」라고 물으면 가진 쪽이 그 뒤의 것만 골라 줍니다. 이 지점을 오프셋 또는 커서라고 부릅니다.
장치를 기다릴 때의 폴링
컴퓨터 안쪽에도 같은 뼈대가 있습니다. 프로그램이 장치에 일을 시켜 놓고 그 일이 끝났는지 알아내는 방법이 둘입니다.
하나는 장치가 다 됐을 때 신호를 보내 프로세서가 하던 일을 잠시 멈추게 하는 것입니다. 이 신호가 인터럽트입니다. 다른 하나는 프로세서가 장치의 상태 값을 되풀이해 읽어 보는 것입니다. 이쪽이 폴링입니다.
둘을 맞대 보면 이렇습니다.
| 인터럽트 | 폴링 | |
|---|---|---|
| 누가 먼저 움직이나 | 장치 | 프로세서 |
| 기다리는 동안 | 다른 일을 한다 | 상태만 되풀이해 읽는다 |
| 맞는 때 | 드물게 일어나는 일 | 아주 잦고 금세 끝나는 일 |
표의 마지막 줄은 뒤집힌 것처럼 보입니다. 일이 아주 잦으면 신호를 받아 하던 일을 멈추고 돌아오는 준비 자체가 부담입니다. 그때는 신호를 끄고 폴링으로 몰아 읽는 편이 일을 더 많이 처리합니다. 준비가 드는 값과 헛도는 값 중에 어느 쪽이 큰지가 갈림입니다.
되풀이해 읽는 동안 그 프로세서는 다른 일을 못 합니다. 다른 일 없이 확인만 되풀이하는 이 기다림을 바쁜 대기라고 부릅니다. 잠금이 풀리기를 이렇게 기다리는 것이 스핀락입니다.
한 번에 여러 연결을 지켜보는 꼴도 있습니다. 연결 수천 개를 하나씩 물으면 느립니다. 그래서 준비된 것이 있는지 커널 에 한꺼번에 묻습니다. 없으면 다음에 다시 묻습니다. 여러 연결을 한 줄기로 돌리는 논블로킹 입출력 이 이 뼈대 위에 앉습니다.
이 방식이 맞는 때와 안 맞는 때
폴링은 낡아서 밀려난 방식이 아니라 조건을 보고 고르는 방식입니다. 아래 셋 중 하나라도 해당하면 폴링이 맞습니다.
- 가진 쪽이 나에게 연락할 길이 없습니다. 방화벽 뒤에 있거나 주소가 자주 바뀌는 쪽은 연락을 못 받습니다
- 늦음이 문제가 안 됩니다. 몇 분에 한 번 갱신하면 되는 화면은 그 간격으로 물으면 끝납니다
- 묻는 쪽이 자기 속도로 일을 집어 가야 합니다. 큐 에서 일감을 가져다 처리하는 쪽은 자기가 감당할 만큼만 가져갑니다. 이 조절이 백프레셔 입니다
안 맞는 때도 분명합니다. 아래 셋이 겹치면 폴링을 접습니다.
- 바뀌는 일이 드뭅니다. 왕복 거의 전부가 「없다」로 끝납니다
- 바뀌었을 때는 곧바로 알아야 합니다. 간격만큼의 늦음이 그대로 남습니다
- 묻는 쪽이 아주 많습니다. 헛도는 왕복이 묻는 쪽 수만큼 곱해집니다
이런 무대에서는 가진 쪽이 먼저 보내는 방식으로 갑니다. 서버가 정해 둔 주소로 알림을 보내는 웹훅, 연결을 열어 둔 채 양쪽이 주고받는 웹소켓, 값이 바뀔 때 알려 달라고 미리 걸어 두는 워치 가 그런 방식입니다.
관련 항목
폴링과 맞세워지는 알림 방식
푸시 · 인터럽트 · 웹훅 · 웹소켓 · Server-Sent Events · 워치 · 발행-구독 · 푸시 알림
폴링의 되풀이를 다듬는 수단
롱 폴링 · 지수 백오프 · 조건부 요청 · ETag · 재시도 · 타임아웃 · 폴링 간격
폴링이 만들어 내는 부하와 그 대응
속도 제한 · HTTP 429 · 재시도 폭풍 · 백프레셔 · 처리량 · 지연 · 대역폭
커널과 장치 쪽에서 폴링을 쓰는 구조
논블로킹 입출력 · 이벤트 루프 · epoll · 시스템 콜 · 디바이스 드라이버 · 커널 · 스핀락 · 라이브락
폴링으로 상태를 걷어 오는 감시 도구와 지표
모니터링 · Prometheus · SNMP · 메트릭 · 시계열 · 하트비트 · 헬스 체크
폴링으로 일감을 집어 가는 처리 방식
큐 · 메시지 큐 · 작업 큐 · 배치 처리 · 스케줄링 · 크론
폴링으로 변경을 따라가는 데이터 동기화 방식
다른 이름: polling