이미지 변환에서 90초 타임아웃이 나고 있었고 노드를 보니 8코어에 프로세스가 열네 개 떠 있었다. 워커를 하나로 줄이면 웹이 여유를 얻지 않겠냐는 질문이 나왔다.
Table of contents
Open Table of contents
프로세스 수로 낸 첫 답
내 첫 답은 열네 프로세스가 8코어를 경합하니 줄이면 나아진다는 것이었다. 프로세스 수만 보고 판단한 것이다.
지적이 하나 왔는데 도착률 대비 단일 워커 처리량이 결정 변수 아니냐는 것이었다. 프로세스를 줄이면 경합은 줄지만 처리량도 줄고 처리량이 도착률보다 낮으면 큐가 쌓인다.
두 값의 실측
프로세스 로그에서 두 가지를 뽑았다. 작업 시작 로그를 분 단위로 세니 도착률이 분당 400건에서 545건 사이였다.
단일 워커 처리량은 작업 소요 시간 분포로 냈다. 단독 실행일 때 약 1.9초이고 지금 경합 상태에서는 29초에서 38초로 20배 지연돼 있었다. 단독 기준으로 환산해도 워커 하나가 분당 31건 정도다.
숫자가 낸 결론
도착률이 분당 400건 이상인데 단일 워커 처리량이 분당 31건이면 워커를 하나로 줄일 경우 분당 수백 건이 적체된다. 웹 굶음은 완화되지만 전체 입점사의 변환이 밀리는 과보정이다.
숫자를 놓고 보니 진짜 문제도 드러났다. 워커 개수가 문제가 아니라 단독 노드 하나에 전체 입점사의 변환 부하가 몰려 있어서 한 노드가 감당할 양이 아니었다. 답은 줄이는 것이 아니라 나누는 것이었고 별도 노드로 분산하거나 이 노드를 카나리에서 해제해 부하 쏠림을 푸는 둘을 냈다.
조건이 바꾼 답
같은 세션 후반에 실제로 워커를 넷에서 하나로 줄였는데 모순이 아니라 조건이 바뀐 것이었다. 앞에서는 전체 변환이 비동기 큐로 들어와 도착률이 분당 수백 건이었다.
뒤에서는 변환이 동기 응답으로 이전되면서 큐는 잔여 부하만 받게 됐고 도착률이 확 떨어졌다. 그 상태에서는 워커 하나로 충분하므로 축소가 성립한다. 절대적인 워커 수는 없고 도착률에 따라 달라지며 도착률은 구조가 바뀌면 바뀐다.
적용 범위와 보이는 값
그래서 워커 수 판단은 항상 현재 비동기 도착률 대비 처리량으로 다시 재기로 하고 그 판단의 적용 범위도 함께 적었다. 전체 입점사 비동기 변환 큐를 단일 노드가 받는 상태라는 조건을 안 적으면 워커를 줄이면 안 된다는 문장만 규칙으로 굳는다.
내가 왜 틀렸는지도 남겨 뒀다. 프로세스 수는 명령 한 번이면 나오지만 도착률과 처리량은 로그를 파싱해야 나온다. 보이는 값으로 판단하고 싶어지는데 보이는 것이 결정 변수가 아니었고 무엇으로 판단할지를 먼저 정한 뒤 그것을 재야 했다.
정리
- 프로세스 수만으로 CPU 경합을 단정하면 안 된다
- 워커 수의 결정 변수는 도착률 대비 처리량이다
- 줄이면 경합은 줄지만 처리량도 줄어 큐가 쌓인다
- 근본이 워커가 많다가 아니라 한 노드가 전체를 받는다일 수 있다
- 답은 줄이는 것이 아니라 나누는 것이다
- 조건이 바뀌면 답도 바뀐다
- 판단에 적용 범위를 명시하지 않으면 규칙으로 굳는다
- 보이는 값이 결정 변수가 아닐 수 있다