Skip to content
isdnetworks
Go back

메시지 하나가 큐를 멈춘다

주문 처리가 멈춰서 큐에는 메시지가 쌓이는데 소비가 전혀 안 되고 있었다. 소비하는 프로세스는 살아 있었고 자원 사용량도 전부 정상이었다.

Table of contents

Open Table of contents

지표가 전부 정상이던 정지

프로세스가 떠 있고 브로커에 연결돼 있고 메모리 사용량도 정상이었다. 인프라 관점에서 보는 지표로는 아무 문제도 나타나지 않았다.

프로세스가 살아 있는데 메시지만 안 나가는 정지는 그 지표들로는 잡히지 않는다. 그래서 소비자 로그를 처음부터 시간순으로 훑어 내려갔다.

하나가 뒤 전부를 막는 이유

정상 처리가 이어지다가 한 지점에서 역직렬화 예외가 나고 그 뒤로 아무것도 없었다. 순서를 보장하는 큐에서는 한 메시지를 처리하지 못하면 진행 위치가 넘어가지 않는다.

다음 메시지로 넘어갈 수가 없으니 뒤에 쌓인 전부가 그 하나를 기다리게 된다. 하나가 전체를 마비시키는 구조라 처리 못 하는 메시지 한 건이 곧 전면 정지였다.

필드 하나가 늘었을 뿐이었다

원인은 상대 시스템이 응답 구조에 필드를 하나 추가한 것이었다. 우리 객체가 모르는 필드를 만나면 예외를 던지게 돼 있었다.

필드 추가는 보통 하위 호환으로 여겨져서 따로 알리지 않는 경우가 많다. 역직렬화에 관용 옵션을 켜서 모르는 필드를 무시하게 하니 막힘이 풀렸다.

공유 컨슈머가 공유하는 실패

이 소비자는 여러 거래처에서 오는 메시지를 한꺼번에 처리하고 있었다. 문제를 일으킨 것은 한 곳인데 다른 곳의 메시지도 같은 줄 뒤에 서 있었다.

제보가 온 곳은 외부 대사 시스템을 써서 먼저 알아챈 한 곳뿐이었으므로 제보 범위가 장애 범위가 아니었다. 처리 못 하는 메시지를 몇 번 재시도한 뒤 별도 큐로 보내고 진행 위치를 넘기게 했고 큰 거래처는 소비자를 분리했다.

커밋 시점과 발효 시점

이 취약점을 만든 코드 변경은 몇 달 전이었는데 장애는 최근이었다. 상대가 필드를 추가한 시점이 촉발 조건이었다.

우리 코드는 그동안 계속 취약한 상태였고 촉발 조건만 나중에 온 것이다. 최근에 무엇을 바꿨는지로만 찾으면 안 나오므로 외부 변화도 함께 봐야 했다.

정리


Share this post on:

Previous Post
0건 수집이 0건 존재는 아니다
Next Post
보안 점검 항목을 우리 코드에 대 보면