死信Exchange

更新时间:

云消息队列 RabbitMQ 版的死信Exchange适用于处理被消费者否定应答或重试失败的消息。本文介绍死信Exchange的核心概念、路由流程、配置方式、注意事项和更多信息。

核心概念

  • 死信Exchange

    • 用于路由死信消息的Exchange。死信Exchange会根据Binding Key、死信Routing Key、Header属性将死信消息投递至死信Queue。死信Exchange可以是任何一种常见类型的Exchange,例如Direct Exchange。

  • 死信Routing Key

    • 死信消息的路由规则。如果不设置死信消息的Routing Key,则死信消息的Routing Key默认为消息本身的Routing Key。

  • 死信消息

    • 被重新发送到死信Exchange的消息。消息变成死信消息的可能原因如下:

      • requeue参数被设置为 false,消费者使用basic.rejectbasic.nack否定应答(NACK)消息。

      • 消息重试次数超过16次,消息重试失败。具体信息,请参见消费重试策略

      • 消息过期,即消息在Queue中存在的时间超过了设置的消息存活时间。具体信息,请参见消息存活时间

  • 死信Queue

    • 死信Exchange绑定的Queue,用于存储死信消息。

路由流程

死信Exchange路由死信消息的流程如下:

  1. 生产者将消息发送到Exchange。

  2. Exchange将消息路由到Queue。

  3. 消费者从Queue拉取消息。

  4. 消费者消费失败后消息重试次数超过16次依然没有成功,或者消费者没有消费消息而直接否定应答,消息变成死信消息。

  5. Queue根据x-dead-letter-exchange将死信消息发送到死信Exchange,并根据x-dead-letter-routing-key为死信消息设置死信Routing Key。

  6. 死信Exchange将死信消息路由到死信Queue。

dg_dead_letter_message_flow

注意事项

  • 云消息队列 RabbitMQ 版不支持跨Vhost路由死信消息,即Queue被指定的死信Exchange必须和该Queue在同一个Vhost内。

  • 云消息队列 RabbitMQ 版不支持修改Queue的死信Exchange。如果您需要修改某个Queue的死信Exchange,您需要删除该Queue后,在重新创建时设置死信Exchange。

配置方式

云消息队列 RabbitMQ 版支持以下方式配置死信Exchange:

控制台

您可以在云消息队列 RabbitMQ 版控制台创建Queue时,为其配置死信Exchange。

  1. 登录云消息队列 RabbitMQ 版控制台

  2. 概览页面的资源分布区域,选择地域。

  3. 实例列表页面,单击目标实例名称。

  4. 在左侧导航栏,单击Queue 列表

  5. Queue 列表页面,在当前 Vhost右侧的切换下拉列表中,选择Vhost,单击创建 Queue

  6. 创建 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-exchangex-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

包含更多关于死信的详细信息的数组。

  • reason: 成为死信时的原因。

  • queue: 成为死信时的队列。

  • exchange: 成为死信时的交换机。

  • routing-keys: 成为死信时的路由键。

  • count: 在queue上因为reason成为死信的次数。

  • time: 成为死信的时间。

消息成为死信消息的可能原因如下:

  • expired(消息过期)

  • nack(消息nack且requeue为false)

  • reject(消息被拒绝且requeue为false)

  • exceed consumer times(消费次数超限)

开启死信队列的TTL功能

默认情况下,死信消息进入死信队列后,TTL(Time-To-Live,存活时间)功能会被禁用,这意味着死信消息进入死信队列后,不会因存活时间到期而路由到其它死信队列或被自动删除。您可以通过控制台启用实例的死信队列TTL功能。启用后,死信消息被转移到死信队列后,将遵循死信队列设置的TTL能力,在存活时间过期后被转发到其它死信队列。

实例限制

支持开启TTL功能的实例类型有:Serverless系列实例、预付费系列实例中的企业版和铂金版。

操作步骤

  1. 云消息队列 RabbitMQ 版实例列表页面,单击目标实例名称。

  2. 实例详情页面,单击实例使用限制页签。

  3. 是否支持死信队列的TTL功能右侧单击开通,为死信队列开启TTL功能。

重要
  • 在配置死信队列时,存在形成消息循环的风险。例如,将队列A的死信队列设置为队列B,并将队列B的死信队列设置为队列A,那么会形成一个死信消息的循环路由。如果在整个路由循环中没有出现任何消息拒绝(reject)事件,一旦检测到这种循环,涉及的死信消息将不再具有TTL功能。

  • 死信消息在多个队列间的路由次数限制为最多16次,一旦达到路由次数上限,相关死信消息将不再具有TTL功能。

更多信息

关于如何删除死信Exchange和为死信Exchange绑定死信Queue,请参见Exchange管理