RabbitMQ 메시지가 unacked에 쌓일 때, broker는 보통 꽤 유용한 힌트를 주고 있습니다. 메시지는 이미 consumer에게 전달됐지만, consumer가 아직 acknowledgement를 보내지 않았다는 뜻이기 때문입니다.
짧게 말하면 먼저 acknowledgement mode를 확인하고, 그다음 handler latency와 prefetch를 비교해야 합니다. queue나 broker 자체를 먼저 의심하는 건 보통 늦습니다.
이 글은 unacked를 막연한 RabbitMQ 장애로 보지 않고, 더 빠르게 좁혀가는 방법을 정리합니다.
unacked가 실제로 뜻하는 것
RabbitMQ 메시지 상태는 여기서 중요합니다.
- ready for delivery
- delivered but not yet acknowledged
unacked는 두 번째 상태입니다. broker는 이미 메시지를 consumer에게 넘겼고, 아직 acknowledgement를 기다리고 있습니다.
즉 이건 보통 publishing 문제가 아니라, consumer나 workflow 쪽 문제입니다.
acknowledgement mode부터 보기
RabbitMQ는 automatic acknowledgement와 manual acknowledgement를 모두 지원합니다.
manual acknowledgement에서는 consumer가 delivery를 명시적으로 ack해야 합니다. 그렇지 않으면 broker는 그 메시지를 unacknowledged 상태에 계속 둡니다.
그래서 첫 질문은 아주 단순합니다.
- ack가 manual인가
- 코드에서
ack는 어디서 일어나는가 - 그 경로가 실패하거나 끝까지 가지 못할 수 있는가
왜 prefetch를 바로 같이 봐야 하나
RabbitMQ 문서에서 prefetch는 ack되지 않은 delivery가 in-flight로 유지될 수 있는 상한으로 설명됩니다.
즉 prefetch가 높으면 시스템이 기술적으로는 동작 중이어도 unacked가 크게 보일 수 있습니다.
대표 패턴은 이렇습니다.
- consumer 속도에 비해 prefetch가 너무 높다
- 오래 걸리는 handler가 delivery를 오래 붙잡는다
- 여러 consumer가 각각 큰 in-flight window를 가진다
- QoS 기본값이 outstanding work를 너무 많이 허용한다
unacked 증가를 해석하는 쉬운 관점
unacked는 종종 숨겨진 backlog가 쌓이는 곳입니다.
handler가 느리거나 ack가 늦으면, 일은 이미 consumer에게 넘어갔기 때문에 messages_ready는 그렇게 커 보이지 않을 수 있습니다. 그래서 겉으로는 덜 심각해 보이지만, 실제로는 pressure가 안쪽으로 숨어 들어갑니다.
즉 unacked 증가가 뜻하는 것은 보통 이렇습니다.
- consumer는 일을 받고 있다
- 일이 충분히 빨리 끝나지 않는다
- acknowledgement loop가 진짜 압박 지점이다
흔한 root cause
1. consumer가 고장 난 게 아니라 느리다
handler는 동작하지만, 처리 시간이 예상보다 길어집니다.
2. ack 코드가 없거나 도달되지 않는다
예외, timeout, retry wrapper 때문에 ack 경로가 건너뛰어질 수 있습니다.
3. prefetch가 너무 높다
consumer가 앞선 메시지를 끝내기 전에 더 많은 메시지를 받아버립니다.
4. consumer connection이 불안정하다
connection이나 channel churn이 delivery와 requeue를 더 헷갈리게 만들 수 있습니다.
unacked와 ready를 혼동하지 않기
queue length는 ready 메시지 기준으로 보이는 경우가 많습니다. unacknowledged는 다른 상태입니다.
그래서 아래처럼 보일 수 있습니다.
- ready는 보통 수준
unacked는 매우 높음- consumer는 과부하
이 둘을 같이 보지 않으면 queue가 “멀쩡해 보이는” 착시가 생깁니다.
실전 점검 순서
1. ready와 unacked를 비교한다
문제가 delivery 전인지 delivery 후인지 먼저 나눕니다.
2. consumer 로그에서 ack 경로를 확인한다
broker가 문제처럼 보여도 실제론 앱 코드의 ack 경로가 빠진 경우가 많습니다.
3. prefetch를 점검한다
prefetch가 높으면 느린 consumer가 감당해야 할 in-flight work가 과하게 커질 수 있습니다.
4. handler latency와 downstream dependency를 본다
느린 downstream은 다른 경보보다 먼저 unacked 증가로 드러날 때가 많습니다.
5. 실패가 endless requeue를 만들고 있는지 확인한다
하나의 나쁜 경로가 계속 churn을 만드는 경우가 있습니다.
바로 확인할 수 있는 명령들
rabbitmqctl list_queues name messages_ready messages_unacknowledged consumers
rabbitmqctl list_channels connection name messages_unacknowledged
rabbitmqctl list_consumers
이 명령으로 active consumer와 inactive consumer, channel의 in-flight 상태를 함께 비교할 수 있습니다.
unacked incident를 볼 때의 실전 관점
가장 좋은 질문은 보통 “RabbitMQ가 왜 메시지를 안 움직이지?”가 아니라 “acknowledgement completion을 무엇이 막고 있지?”입니다.
이렇게 보면 조사가 훨씬 빨라집니다. 실제로 unacked는 보통 아래 이유로 커집니다.
- handler 작업이 예상보다 느리다
- acknowledgement 경로가 건너뛰어진다
- 한 번에 허용되는 in-flight work가 너무 많다
- 실패가 같은 작업을 계속 재큐잉한다
broker failure보다 acknowledgement completion 관점으로 보면, 어떤 로그와 지표를 봐야 할지가 훨씬 분명해집니다.
FAQ
Q. unacked는 메시지 유실을 뜻하나요?
아니요. 전달은 되었지만 아직 ack되지 않았다는 뜻입니다.
Q. unacked가 높다고 항상 나쁜 건가요?
항상은 아닙니다. in-flight work로서 정상일 수 있지만, 빠지지 않고 계속 쌓이면 문제가 됩니다.
Q. 가장 빠른 첫 단계는 무엇인가요?
consumer 재시작 전에 acknowledgement mode와 prefetch를 먼저 확인하는 것입니다.
Q. 언제 consumer 코드를 먼저 의심해야 하나요?
broker가 메시지를 분명히 전달했는데도 unacked 상태에서 전혀 내려오지 않을 때입니다.
Read Next
- queue 전체가 커지는 증상이라면 RabbitMQ Queue Keeps Growing를 보세요.
- 다음 점검 항목이 prefetch라면 RabbitMQ Prefetch Guide를 보세요.
- 같은 pressure에서 publisher도 느려진다면 RabbitMQ Connection Blocked를 보세요.
Related Posts
- RabbitMQ Queue Keeps Growing
- RabbitMQ Prefetch Guide
- RabbitMQ Connection Blocked
- RabbitMQ Consumers Not Receiving Messages
Sources:
- https://www.rabbitmq.com/docs/queues
- https://www.rabbitmq.com/docs/confirms
- https://www.rabbitmq.com/docs/4.0/consumer-prefetch
심사 대기 중에는 광고 대신 관련 가이드를 먼저 보여줍니다.
먼저 읽어볼 가이드
검색 유입이 많은 핵심 글부터 이어서 보세요.
- 미들웨어 트러블슈팅 가이드: Redis vs RabbitMQ vs Kafka 개발자를 위한 미들웨어 트러블슈팅 허브 글입니다. Redis, RabbitMQ, Kafka 중 어떤 증상부터 먼저 봐야 하는지와 어떤 문제 패턴이 각 시스템에 가까운지 정리합니다.
- Kubernetes CrashLoopBackOff: 먼저 볼 것들 startup failure, probe, config, resource limit 관점에서 CrashLoopBackOff를 어떻게 나눠서 봐야 하는지 정리한 가이드입니다.
- Kafka consumer lag가 계속 늘 때: 트러블슈팅 가이드 Kafka consumer lag가 계속 늘어날 때 무엇부터 봐야 하는지 정리합니다. poll 주기, 처리 속도, rebalance, consumer 설정까지 실전 기준으로 다룹니다.
- Kafka Rebalancing Too Often 가이드 Kafka consumer group에서 rebalance가 너무 자주 일어날 때 membership flapping, poll timing, protocol, assignment churn을 어떤 순서로 봐야 하는지 설명하는 실전 가이드입니다.
- Docker container가 계속 재시작될 때: 먼저 확인할 것들 exit code, command failure, environment mistake, health check 관점에서 Docker restart loop를 푸는 실전 가이드입니다.
심사 대기 중에는 광고 대신 관련 가이드를 먼저 보여줍니다.