@RabbitListener 的并发度怎么设?max-concurrency 真的会自动扩容吗?prefetch 默认 250 有什么坑?消费抛异常为什么 CPU 被打满?kill -9 之后消息会不会丢?这篇在 Spring AMQP 4.0.5 和真实的 RabbitMQ 上逐项实测。
[默认(concurrency=1)] 队列上的消费者数 1;20 条处理完共 4.1 秒;参与的线程 ['#0-1'] [concurrency=4] 队列上的消费者数 4;20 条处理完共 1.0 秒;参与的线程 ['#0-1', '#0-2', '#0-3', '#0-4'] [concurrency=1, max-concurrency=4] 队列上的消费者数 1;20 条处理完共 4.1 秒;参与的线程 ['#0-1']
concurrency 启动时创建;max-concurrency 对短突发不起作用。
[prefetch 默认(250)] 刚发完 0.4 秒时队列 ready=0、unacked=5;10 条全部处理完共 5.0 秒;各线程处理条数 {'#0-1': 5, '#0-2': 5},其中 1000 ms 的慢消息 {'#0-2': 5}
[prefetch=1] 刚发完 0.4 秒时队列 ready=7、unacked=2;10 条全部处理完共 3.1 秒;各线程处理条数 {'#0-1': 5, '#0-2': 5},其中 1000 ms 的慢消息 {'#0-1': 3, '#0-2': 2}默认 250 让慢消息集中在一个消费者上。
[默认(AUTO 确认,default-requeue-rejected 默认 true)] 3 秒内 poison-1 被投递 37670 次;ok-2 是否被处理 True;队列剩余 ready=0 unacked=1 [default-requeue-rejected=false] 3 秒内 poison-1 被投递 1 次;ok-2 是否被处理 True;队列剩余 ready=0 unacked=0
默认拒绝并重新入队,形成死循环。
[AUTO] 处理中(消息发出 0.8 秒后):ready=0 unacked=4 consumers=1
kill -9 之后:ready=4 unacked=0
重启应用后收到的消息:['m2(redelivered)', 'm3(redelivered)', 'm4(redelivered)', 'm5(redelivered)'];其中标记为 redelivered 的 4 条
[NONE(自动确认,autoAck)] 处理中(消息发出 0.8 秒后):ready=0 unacked=0 consumers=1
kill -9 之后:ready=0 unacked=0
重启应用后收到的消息:[];其中标记为 redelivered 的 0 条
[MANUAL(代码里自己 basicAck;noack-1 故意不确认)] 处理中(消息发出 0.8 秒后):ready=0 unacked=5 consumers=1
kill -9 之后:ready=5 unacked=0
重启应用后收到的消息:['m2(redelivered)', 'm3(redelivered)', 'm4(redelivered)', 'm5(redelivered)', 'noack-1(redelivered)'];其中标记为 redelivered 的 5 条AUTO / MANUAL 进程被杀不丢消息;NONE 会丢。