云消息队列 RabbitMQ 版的死信Exchange适用于处理被消费者否定应答或重试失败的消息。本文介绍死信Exchange的核心概念、路由流程、配置方式、注意事项和更多信息。
核心概念
死信Exchange
用于路由死信消息的Exchange。死信Exchange会根据Binding Key、死信Routing Key、Header属性将死信消息投递至死信Queue。死信Exchange可以是任何一种常见类型的Exchange,例如Direct Exchange。
死信Routing Key
死信消息的路由规则。如果不设置死信消息的Routing Key,则死信消息的Routing Key默认为消息本身的Routing Key。
死信消息
死信Queue
死信Exchange绑定的Queue,用于存储死信消息。
路由流程
死信Exchange路由死信消息的流程如下:
生产者将消息发送到Exchange。
Exchange将消息路由到Queue。
消费者从Queue拉取消息。
消费者消费失败后消息重试次数超过16次依然没有成功,或者消费者没有消费消息而直接否定应答,消息变成死信消息。
Queue根据x-dead-letter-exchange将死信消息发送到死信Exchange,并根据x-dead-letter-routing-key为死信消息设置死信Routing Key。
死信Exchange将死信消息路由到死信Queue。
注意事项
云消息队列 RabbitMQ 版不支持跨Vhost路由死信消息,即Queue被指定的死信Exchange必须和该Queue在同一个Vhost内。
云消息队列 RabbitMQ 版不支持修改Queue的死信Exchange。如果您需要修改某个Queue的死信Exchange,您需要删除该Queue后,在重新创建时设置死信Exchange。
配置方式
云消息队列 RabbitMQ 版支持以下方式配置死信Exchange:
控制台
您可以在云消息队列 RabbitMQ 版控制台创建Queue时,为其配置死信Exchange。
在概览页面的资源分布区域,选择地域。
在实例列表页面,单击目标实例名称。
在左侧导航栏,单击Queue 列表。
在Queue 列表页面,在当前 Vhost右侧的切换下拉列表中,选择Vhost,单击创建 Queue。
在创建 Queue面板,在Queue 名称文本框输入Queue的名称,选择是否为Auto Delete类型,单击高级选项,设置Queue的参数,然后单击确定。
参数
描述
说明
Queue 名称
Queue的名称
只能包含字母、数字、短划线(-)、下划线(_)、半角句号(.)、井号(#)、正斜线(/)、at符号(@)。
长度限制在1~255字符。
创建后无法修改,只能删除重建。
以amq.开头的为保留字段,因此不能使用。例如:amq.test。
Auto Delete
最后一个Consumer取消订阅后,Queue是否自动删除。
true:在订阅该Queue消息的最后一个Consumer取消订阅该Queue的消息后,自动删除该Queue。
false:在订阅该Queue消息的最后一个Consumer取消订阅该Queue的消息后,不自动删除该Queue。
高级选项
Queue的参数设置,可用于设置死信Exchange、死信Routing Key和消息存活时间。
DeadLetterExchange:指定死信消息发送的目标Exchange。
DeadLetterRoutingKey:指定死信消息的Routing Key,即死信Exchange会将消息发送至匹配该死信Routing Key所对应的Queue。
MessageTTL:消息存活时间,单位毫秒(ms)。在指定时间内未被成功消费的消息会变成死信消息,该消息将会被发送到死信Exchange。更多信息,请参见消息存活时间。
API
您可以在通过API创建Queue时,为其配置死信Exchange。更多信息,请参见CreateQueue。
客户端
您可以在云消息队列 RabbitMQ 版客户端声明Queue时,为其配置死信Exchange。
通过x-dead-letter-exchange和x-dead-letter-routing-key设置死信消息要发送的Exchange以及死信消息的Routing Key。
例如,声明一个名称为some.exchange.name
、类型为direct
的Exchange,使用 x-dead-letter-exchange将该Exchange设置为死信Exchange,使用x-dead-letter-routing-key将死信消息的Routing Key设置为demo-routing-key
。
Java示例代码如下:
channel.exchangeDeclare("some.exchange.name", "direct");
Map<String, Object> args = new HashMap<String, Object>();
arguments.put("x-dead-letter-exchange", "some.exchange.name");
arguments.put("x-dead-letter-routing-key", "demo-routing-key");
channel.queueDeclare("MyQueue", false, false, false, arguments);
死信Header
死信消息Header中包含以下信息:
Header | 说明 |
x-first-death-exchange | 消息第一次成为死信时的交换机。 |
x-first-death-queue | 消息第一次成为死信时的队列。 |
x-first-death-reason | 消息第一次成为死信时的原因。 |
x-death-total | 消息成为死信的次数。 |
x-death | 包含更多关于死信的详细信息的数组。
|
消息成为死信消息的可能原因如下:
expired(消息过期)
nack(消息nack且requeue为false)
reject(消息被拒绝且requeue为false)
exceed consumer times(消费次数超限)
开启死信队列的TTL功能
默认情况下,死信消息进入死信队列后,TTL(Time-To-Live,存活时间)功能会被禁用,这意味着死信消息进入死信队列后,不会因存活时间到期而路由到其它死信队列或被自动删除。您可以通过控制台启用实例的死信队列TTL功能。启用后,死信消息被转移到死信队列后,将遵循死信队列设置的TTL能力,在存活时间过期后被转发到其它死信队列。
实例限制
当前仅企业版、铂金版和Serverless实例支持开启TTL功能。
操作步骤
在云消息队列 RabbitMQ 版实例列表页面,单击目标实例名称。
在实例详情页面,单击实例使用限制页签。
在是否支持死信队列的TTL功能右侧单击开通,为死信队列开启TTL功能。
在配置死信队列时,存在形成消息循环的风险。例如,将队列A的死信队列设置为队列B,并将队列B的死信队列设置为队列A,那么会形成一个死信消息的循环路由。如果在整个路由循环中没有出现任何消息拒绝(reject)事件,一旦检测到这种循环,涉及的死信消息将不再具有TTL功能。
死信消息在多个队列间的路由次数限制为最多16次,一旦达到路由次数上限,相关死信消息将不再具有TTL功能。
更多信息
关于如何删除死信Exchange和为死信Exchange绑定死信Queue,请参见Exchange管理。