来自一个队列的消息能够被当作‘死信’,即被从新发布到另一个“exchange”去,这样的状况有:
- 消息被拒绝 (basic.reject or basic.nack) 且带 requeue=false 参数
- 消息的TTL-存活时间已通过期
- 队列长度限制被超越(队列满)
Dead letter exchanges (DLXs) are normal exchanges.
For any given queue, a DLX can be defined by clients using the queue's arguments, or in the server using policies.
Dead Letter Pattern
“死信”模式指的是,当消费者不能处理接收到的消息时,将这个消息从新发布到另一个队列中,等待重试或者人工干预。
这个过程当中的exchange和queue就是所谓的"Dead Letter Exchange 和 Queue"。
关键是如何区分“消费失败”和“处理失败”?消费失败须要送到死信队列,而处理失败不须要。大部分状况都属于“处理失败”。
Dead-Letter-Exchange, routing-key, queue 均可以从 rabbitmq 的管理后台配置。
若是用 Spring-rabbitmq 来使用 Dead-Letter-Exchange 和 Queue 须要对。
从 3.9 Exception Handling 能够知道,设置 defaultRequeueRejected = false 会丢弃消息或者从新发布到死信队列中。
若是是 Convert 出现异常,那么会直接 "reject-dont-requeue".
<
rabbit:listener-container
defaultRequeueRejected="false"
connection-factory
=
"connectionFactory"
>
<
rabbit:listener
ref
=
"listener"
method
=
"listen"
queue-names
=
"async_request_queue"
/>
</rabbit:
listener-container>
|
也能够在 handler 中抛出 "AmqpRejectAndDontRequeueException" 来告诉spring容器,不要从新requeue这条消息。
而后配置 Dead Letter Exchange 并绑定 Dead Letter Queue.
<rabbit:queue name="q.with.dlx">
<rabbit:queue-arguments>
<entry key="x-dead-letter-exchange" value="dlx"/>
<entry key="x-message-ttl" value="10000" value-type="java.lang.Long"/>
</rabbit:queue-arguments>
</rabbit:queue>
<rabbit:queue name="dlq"/>
<rabbit:direct-exchange name="dlx">
<rabbit:bindings>
<rabbit:binding key="q.with.dlx" queue="dlq"/>
</rabbit:bindings>
</rabbit:direct-exchange>
若是 exchange 或者 queue 是 镜像/持久的,那么须要先删除再启动 spring-amqp 程序,这样 xml 中的 exchange 和 queue 配置才能生效,
不然服务器端配置不会修改,启动生成者时抛异常,启动失败。
对于部署,能够考虑使用新队列来避免须要先删除已有队列的问题。
常见问题:
缘由:queue已经存在,可是启动 consumer 时试图设定一个 x-dead-letter-exchange 参数,这和服务器上的定义不同,server 不容许因此报错。若是删除 queue 从新 declare 则不会有问题。或者经过 policy 来设置这个参数也能够不用删除队列。
参考: