← 홈Setup Tip

Setup Tip

Setup Tip — 부하를 탓하기 전에 대기열 시간부터 재라

응답이 느려지고 load average가 높게 보이면 "호스트가 바쁘다"는 결론이 가장 먼저 떠오른다. 하지만 CPU가 절반 가까이 놀고 있는데도 요청이 수십 초씩 기다릴 수 있다. 작은 고정 크기 작업 풀을 백그라운드 폴링이 전부 차지하면, 사용자 요청은 CPU가 아니라 줄에서 기다린다. 도착 시각과 처리 시작 시각의 차이를 먼저 재라.

상황

에이전트 게이트웨이처럼 들어온 메시지를 받아 작업을 시작시키는 서비스가, 보조 명령줄 도구를 호출할 때 동시에 몇 개만 돌도록 작은 풀을 둔다고 하자. 같은 서비스가 백그라운드 작업의 상태를 짧은 주기로 확인하는 관찰자도 돌린다. 어느 날 사용자는 "답이 늦게, 끝에 한꺼번에 온다"고 말하고, 확인해 보니 호스트의 load average도 높다.

흔한 오진

load average가 높으니 호스트가 과부하라는 결론을 내리고, 동시에 돌고 있는 작업 수를 줄이라는 처방을 내놓기 쉽다. 그런데 CPU 사용률을 보면 거의 절반이 유휴 상태다. load average는 실행 대기뿐 아니라 여러 종류의 대기를 한 숫자로 뭉쳐 보여 주는 지표라서, 그것만으로는 "누가 무엇을 기다리는가"를 알 수 없다. 이 단계에서 부하를 탓하면 증상은 그대로 남고 멀쩡한 작업만 멈춘다.

실제로 일어난 일

요청이 도착한 시각과 처리가 시작된 시각의 차이를 재 보면, 한가할 때는 2초 안팎이던 것이 문제 구간에서는 수십 초, 길게는 2분 넘게 벌어져 있다. 그 사이 보조 도구 풀의 슬롯은 항상 꽉 차 있었고, 차지한 쪽은 수백 밀리초마다 상태를 묻는 백그라운드 관찰자들이었다. 사용자 요청에 필요한 호출은 한 번에 1~3초짜리인데, 선입선출 줄에서 폴링 호출들 뒤에 계속 밀렸다. CPU가 아니라 슬롯이 병목이었다.

무엇을 재야 하는가

세 가지만 있으면 된다. 첫째, 요청별 도착 시각과 처리 시작 시각의 차이. 둘째, 공유 풀의 동시 점유 수와 누가 점유하고 있는지. 셋째, 그 풀을 통과하는 호출 하나의 실제 소요 시간. 대기 시간은 길고 호출 시간은 짧으며 풀이 늘 가득 차 있다면, 원인은 연산량이 아니라 줄 서는 방식이다. 호스트 쪽 의심이 남으면 load average 대신 유휴 비율, 시스템 시간, 문맥 전환 수를 본다.

고치는 방향

사용자와 직접 맞닿은 호출에는 우선순위를 주고, 백그라운드 호출이 쓸 수 있는 슬롯 수에 상한을 둔다. 이미 다른 경로로 변화를 통지받는 관찰자는 폴링 주기를 느리게 바꾼다. 풀 크기를 늘리는 것만으로는 부족하다. 폴링은 늘어난 슬롯도 금방 채우기 때문이다.

확인 방법

수정 후에 같은 지표를 다시 잰다. 도착에서 시작까지의 대기가 한가할 때 수준으로 돌아왔는지, 부하가 걸린 구간에서도 사용자 호출이 폴링 뒤에 서지 않는지 본다. "이제 빨라진 것 같다"는 느낌이 아니라 전후 두 구간의 대기 시간 숫자로 끝을 확인한다.