Skip to content
isdnetworks
Go back

인프라 탓이 아니었던 지연

배치가 중단됐다가 재실행됐는데 예상한 시간 안에 끝나지 않았다. 중단 가능한 저가 인스턴스를 쓰고 있어서 실행 환경 쪽 문제인가 하는 생각부터 들었다.

Table of contents

Open Table of contents

막힌 측정 경로

API 호출이 얼마나 걸리는지를 재려 했는데 쓸 수 있는 두 경로가 다 막혀 있었다. 직접 호출하는 쪽은 인증 토큰이 만료된 상태였다.

프록시로 재현하는 쪽은 응답이 커서 서빙 태스크가 메모리 초과로 죽을 위험이 있었다. 측정하려다 운영을 건드리는 것은 안 되므로 다른 길을 찾아야 했다.

계측 로그에서 분리한 서버 시간

API 서비스에 계측이 이미 있어서 요청마다 총 소요 시간을 로그에 남기고 있었다. 로그 그룹에서 그 값만 필터로 걸러 세 달치를 뽑았다.

내 코드를 안 건드리고 부하도 안 주면서 실제 운영 요청의 값을 얻었다. 직접 측정이 막혔을 때 이미 남고 있는 계측을 쓰는 것이 가장 싸고 실제 값에 가깝다.

서버 밖의 90퍼센트

뽑아 보니 서버 측 소요는 어느 달이든 10초 안팎이었다. 그런데 배치는 월당 2분 가까이 걸리고 있었다.

서버가 12초 정도이고 전체가 120초이니 나머지 108초가 서버 밖에 있었다. 배치 코드에서 무엇을 하는지 보니 대용량 응답을 전송받아 파싱하고 20만 행을 여러 축과 세 기간으로 집계한 뒤 필터와 매핑을 만들고 압축해서 두 번 업로드하고 있었다.

구조적 특성이라는 결론

그중 집계 단계가 가장 컸는데 채널과 카테고리와 셀러와 상품과 키워드를 축으로 당월과 전월과 전년을 각각 돌리니 조합이 많았다.

소요 시간이 실행 환경이나 인스턴스 종류와 무관한 구조적 특성이었다. 중단 가능 인스턴스여서도 아니고 실행 시간 한도 때문도 아니라 원래 그만큼 걸리는 일이었다. 느리다고 인프라 원인을 먼저 의심하면 측정할 곳을 잘못 고르게 된다.

의심했던 다른 후보도 배제했다. 이름 조회를 반복하는 함수가 있었는데 대분류 코드별 캐시가 걸려 있고 코드 종류가 제한적이라 호출이 월당 수십 회로 바운드됐다. 이것을 확인 안 했으면 주범이 아닌 곳을 최적화했을 것이다.

고칠 수 있고 지금은 안 한다

빠르게 하는 방법 자체는 있었는데 집계를 서버 측으로 옮기는 것이다. 그러면 전송량이 수백 분의 일로 줄고 집계도 데이터베이스가 하는 편이 빠르다.

그런데 안 하기로 했고 그 이유가 둘이었다. 원본을 저장소에 보존해서 재집계 입력으로 쓰는 설계 의도가 있어서 서버 집계 결과만 받으면 축이 바뀔 때 다시 만들 원본이 없어진다. 그리고 일 1회 새벽에 5분대이면 아무도 안 기다린다.

느리다는 것이 고쳐야 한다는 뜻은 아니고 언제 도는지와 누가 기다리는지를 봐야 한다. 결론에는 원인이 무엇이고 어떻게 고칠 수 있으며 지금은 안 고친다는 것까지 적었으므로 나중에 요구가 바뀌면 이 문서에서 시작하면 된다.

정리


Share this post on:

Previous Post
Google Play 앱 정책 위반 알림 대응 — 한꺼번에 8건 받았을 때
Next Post
증거가 되는 다이제스트