RabbitMQ 처리량이 이상하게 느껴질 때, prefetch는 가장 먼저 만지기 쉬운 설정이면서도 동시에 가장 오해하기 쉬운 설정 중 하나입니다.
짧게 말하면 prefetch는 속도 조절 노브가 아니라 unfinished work를 얼마나 많이 consumer에게 넘길지 정하는 concurrency window에 가깝습니다. 그래서 값만 따로 조절하지 말고 handler 비용, unacked, 전체 drain rate와 같이 봐야 합니다.
이 글은 prefetch를 마법 같은 throughput 튜닝 값처럼 보지 않고, 더 실전적으로 해석하는 방법을 정리합니다.
먼저 “consumer가 바쁘다”와 “consumer가 실제로 진전이 있다”를 구분하기
prefetch가 높으면 consumer 안에 일이 많이 찬 것처럼 보이지만, 실제 병목은 숨겨질 수 있습니다.
그래서 queue 지표가 이런 식으로 헷갈릴 수 있습니다.
ready는 적당해 보임unacked는 조용히 계속 증가함- 느린 consumer 하나가 delivery를 오래 붙잡음
- backlog가 broker 밖이 아니라 in-flight work 안에 숨어 있음
이 구분 없이 prefetch를 만지면 거의 추측으로 튜닝하게 됩니다.
prefetch가 실제로 제한하는 것
RabbitMQ 문서에서 consumer prefetch는 ack되지 않은 delivery가 in-flight로 유지될 수 있는 상한으로 설명됩니다.
즉 prefetch는 직접적인 throughput 값이 아니라 unfinished work의 concurrency window입니다.
이 값이 뜻하는 것은 아래와 같습니다.
- ack가 오기 전에 consumer에게 얼마나 많은 일을 넘길 수 있는가
- channel 안에 unfinished work가 얼마나 쌓일 수 있는가
반대로 아래를 직접 보장해주지는 않습니다.
- handler가 효율적인가
- downstream 시스템이 건강한가
- end-to-end throughput이 실제로 좋아지는가
왜 “높을수록 좋다”는 모델이 틀리기 쉬운가
handler가 빠르고 예측 가능하고 서로 독립적이라면, 큰 prefetch가 도움이 될 수 있습니다.
하지만 아래처럼 보이면 오히려 해가 될 수 있습니다.
- handler가 느리다
- 처리 시간 편차가 크다
- downstream 시스템에 자주 막힌다
- 메시지 하나의 memory cost가 크다
이런 경우 높은 prefetch는 slowdown을 해결하기보다 그냥 숨기는 역할을 할 때가 많습니다.
이해를 돕는 간단한 사고 방식
메시지 하나 처리 시간이 긴데 prefetch만 높으면, broker는 앞선 delivery가 끝나기 전에 더 많은 unfinished work를 같은 consumer에게 밀어넣을 수 있습니다.
그러면 backlog가 아래에서:
- broker 안의 보이는 queue depth
에서:
- consumer 안의 숨겨진 in-flight work
로 옮겨갑니다.
그래서 prefetch를 바꿀 때는 messages_unacknowledged, handler 시간, drain rate를 함께 봐야 합니다.
prefetch가 안 맞는 것처럼 보이는 신호
1. unacked가 오래 높게 유지된다
consumer가 감당 가능한 것보다 더 많은 일을 오래 붙잡고 있다는 뜻입니다.
2. queue 증가가 실제 slowdown보다 늦게 보인다
backlog가 messages_ready가 아니라 in-flight delivery 안에 숨어 있기 때문입니다.
3. 특정 consumer만 유난히 과부하처럼 보인다
delivery window와 handler 비용 분포가 고르지 않을 수 있습니다.
4. prefetch를 올렸더니 throughput이 오히려 떨어진다
window만 커졌을 뿐 실제 처리 속도는 빨라지지 않은 상태입니다.
prefetch를 무엇과 같이 봐야 하나
prefetch는 아래와 같이 비교할 때 훨씬 해석이 쉬워집니다.
- handler latency
- acknowledgement timing
- downstream dependency latency
- consumer fairness
- in-flight 메시지 하나당 memory cost
좋은 prefetch 값은 queue를 덜 차 보이게 만드는 값이 아니라 workload 모양과 맞는 값인 경우가 많습니다.
실전 점검 순서
1. ready와 unacked를 따로 본다
queue가 broker 안에서 기다리는지, consumer 안에서 unfinished work로 쌓이는지 먼저 나눕니다.
2. handler latency와 prefetch 크기를 비교한다
handler 하나가 이미 느리면, 큰 prefetch는 숨겨진 in-flight backlog만 늘릴 수 있습니다.
3. consumer가 진짜로 일을 비우는지 본다
살아 있는 것처럼 보여도 실제로는 거의 진전이 없을 수 있습니다.
4. window를 줄이거나 늘렸을 때 end-to-end throughput이 바뀌는지 측정한다
이건 가정이 아니라 측정으로 확인해야 합니다.
5. queue backlog나 blocked publisher가 같이 있는지도 본다
그렇다면 prefetch만의 문제는 아닐 가능성이 큽니다.
바로 확인할 수 있는 명령들
rabbitmqctl list_queues name messages_ready messages_unacknowledged consumers
rabbitmqctl list_channels connection name messages_unacknowledged prefetch_count
rabbitmqctl list_consumers
이 명령으로 backlog, in-flight delivery, 실제 channel prefetch 값을 함께 비교할 수 있습니다.
실전에서 가지면 좋은 관점
prefetch를 바꿨더니 지표는 좋아 보이는데 사용자 체감 throughput은 그대로라면, 병목이 사라진 것이 아니라 다른 곳으로 옮겨간 것일 가능성이 큽니다.
그래서 prefetch는 만능 최적화 스위치가 아니라, workload를 shaping하는 파라미터로 보는 편이 맞습니다.
FAQ
Q. prefetch를 높이면 throughput이 항상 좋아지나요?
아니요. 어떤 workload에서는 좋아지지만, 어떤 경우에는 visibility와 fairness를 크게 해칠 수 있습니다.
Q. prefetch를 볼 때 무엇을 같이 봐야 하나요?
unacked, handler latency, 전체 drain rate를 같이 봐야 합니다.
Q. 가장 빠른 첫 단계는 무엇인가요?
prefetch 값을 바꾸기 전에 messages_ready와 messages_unacknowledged를 먼저 비교하는 것입니다.
Q. 다음으로 같이 보면 좋은 글은 무엇인가요?
보통 RabbitMQ Messages Stuck in unacked와 RabbitMQ Queue Keeps Growing입니다.
Read Next
- prefetch 때문에 in-flight work가 과하게 쌓였다면 RabbitMQ Messages Stuck in unacked를 보세요.
- queue backlog가 더 눈에 띄는 증상이라면 RabbitMQ Queue Keeps Growing를 보세요.
- consumer가 붙어 있는데도 delivery를 못 받는다면 RabbitMQ Consumers Not Receiving Messages를 보세요.
Related Posts
- RabbitMQ Messages Stuck in unacked
- RabbitMQ Queue Keeps Growing
- RabbitMQ Consumers Not Receiving Messages
- RabbitMQ Connection Blocked
Sources:
심사 대기 중에는 광고 대신 관련 가이드를 먼저 보여줍니다.
먼저 읽어볼 가이드
검색 유입이 많은 핵심 글부터 이어서 보세요.
- 미들웨어 트러블슈팅 가이드: 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를 푸는 실전 가이드입니다.
심사 대기 중에는 광고 대신 관련 가이드를 먼저 보여줍니다.