重试了几次、间隔多久?max-attempts 为什么不管用了?重试用完消息去哪了?重试会不会堵住其他消息?怎么做不阻塞的延迟重试?消息格式错了会不会死循环?这篇在 Spring AMQP 4.0.5 和真实 RabbitMQ 上逐项实测。
监听方法被调用 4 次,时刻 [0.0, 0.5, 1.5, 3.6] 秒;重试用完之后队列状态 (0, 0)(ready, unacked);消息去哪了:没有死信配置,被丢弃
原地重试,间隔指数增长,用完默认丢弃。
max-attempts=1:被调用 4 次 max-attempts=2:被调用 4 次 max-retries=0:被调用 1 次 max-retries=1:被调用 2 次 max-retries=2:被调用 3 次
max-attempts 被忽略,总调用次数 = max-retries + 1。
重试用完之后:q.work=(0, 0),q.dlq=(1, 0)
q.dlq 里的消息:{'body': 'poison-1', 'x-first-death-reason': 'rejected', 'x-first-death-queue': 'q.work', 'x-death 条目': [('q.work', 'rejected', 1L)]}队列上配 DLX,消息带 x-death 头进入。
ok-2 在 [7.0] 秒才被处理(poison-1 占着唯一的消费者线程重试了约 7 秒)
占住消费者线程,堵住后面的消息。
0.0 秒 收到 poison-1
0.0 秒 收到 ok-2
0.0 秒 完成 ok-2
0.7 秒 收到 poison-1(x-death 累计 2 次)
1.4 秒 收到 poison-1(x-death 累计 4 次)
1.4 秒 已重试 3 次,转存到 q.parking 并确认
最终队列状态:{'q.wait': (0, 0), 'q.work': (0, 0), 'q.dlq': (0, 0), 'q.parking': (1, 0)}TTL 队列加死信,不阻塞;x-death 每轮加 2。
监听方法被调用 0 次;3 秒后 q.work=(0, 1),q.dlq=(1, 0);再过 3 秒 q.work=(0, 0),q.dlq=(1, 0)
q.dlq 里的消息:{'body': 'this is not json', 'x-first-death-reason': 'rejected', 'x-first-death-queue': 'q.work', 'x-death 条目': [('q.work', 'rejected', 1L)]}致命异常,不重试直接进死信。