RabbitMQ-死信队列

简介

DLX,全称为Dead-Letter-Exchange,可以称之为死信交换机,也有人称为死信邮箱。当消息在一个队列中变成死信(dead message)之后,它能被重新发送到另一个交换机中,这个交换机就是DLX,绑定DLX的队列称之为死信队列。

消息变成死信,可能是由于一下原因:

  • 消息被拒绝
  • 消息过期
  • 队列达到最大长度

DLX也是一个正常的交换机,和一般的交换机没有区别,它能在任何的队列上被指定,实际上就是设置某一个队列的属性。当这个队列中存在死信时,RabbitMQ就会自动地将这个消息重新发布到设置的DLX上去,进而被路由到另一个队列,即死信队列。

要想使用死信队列,只需要在定义队列的时候设置队列参数x-dead-letter-exchange指定交换机即可。

使用方式

定义死信交换机

在rabbitmq的配置文件spring-rabbitmq.xml添加配置:

1
2
3
4
5
6
7
8
9
<!--定义定向交换机中的持久化死信队列,不存在则自动创建-->
<rabbit:queue id="my_dlx_queue" name="my_dlx_queue" auto-declare="true"/>
<!--定义广播类型交换机;并绑定上述两个队列-->
<rabbit:direct-exchange name="my_dlx_exchange" id="my_dlx_exchange" auto-declare="true">
<rabbit:bindings>
<rabbit:binding key="my_ttl_dlx" queue="my_dlx_queue"></rabbit:binding>
<rabbit:binding key="my_max_dlx" queue="my_dlx_queue"></rabbit:binding>
</rabbit:bindings>
</rabbit:direct-exchange>

队列设置死信交换机

为了测试消息在过期、队列达到最大长度后都将被投递到死信交换机上;所以添加配置如下:

在rabbitmq的配置文件spring-rabbitmq.xml添加配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!--定义定向交换机中的持久化死信队列,不存在则自动创建-->
<rabbit:queue id="my_dlx_queue" name="my_dlx_queue" auto-declare="true"/>
<!--定义广播类型交换机;并绑定上述两个队列-->
<rabbit:direct-exchange name="my_dlx_exchange" id="my_dlx_exchange" auto-declare="true">
<rabbit:bindings>
<!--绑定路由键my_ttl_dlx、my_max_dlx,可以将过期的消息转移到my_dlx_queue队列-->
<rabbit:binding key="my_ttl_dlx" queue="my_dlx_queue"></rabbit:binding>
<rabbit:binding key="my_max_dlx" queue="my_dlx_queue"></rabbit:binding>
</rabbit:bindings>
</rabbit:direct-exchange>

<!--定义过期队列及属性,不存在则自动创建-->
<rabbit:queue id="my_ttl_dlx_queue" name="my_ttl_dlx_queue" auto-declare="true">
<rabbit:queue-arguments>
<!--投递到该队列的消息如果没有消费都将在6秒之后被删除-->
<entry key="x-message-ttl" value-type="long" value="6000"/>
<!--当消息过期后,投递到对应的死信交换机-->
<entry key="x-dead-letter-exchange" value="my_dlx_exchange"/>
</rabbit:queue-arguments>
</rabbit:queue>
<!--定义限制长度的队列及属性,不存在则自动创建-->
<rabbit:queue id="my_max_dlx_queue" name="my_max_dlx_queue" auto-declare="true">
<rabbit:queue-arguments>
<!--投递到该队列的消息最多2个消息,如果超过则最早的消息被删除投递到死信交换机-->
<entry key="x-max-length" value-type="long" value="2"/>
<!--当消息长度超过2个,最早的会投递到对应的死信交换机-->
<entry key="x-dead-letter-exchange" value="my_dlx_exchange"/>
</rabbit:queue-arguments>
</rabbit:queue>


<rabbit:direct-exchange name="my_normal_exchange" id="my_normal_exchange" auto-declare="true">
<rabbit:bindings>
<rabbit:binding key="my_ttl_dlx" queue="my_ttl_dlx_queue"></rabbit:binding>
<rabbit:binding key="my_max_dlx" queue="my_max_dlx_queue"></rabbit:binding>
</rabbit:bindings>
</rabbit:direct-exchange>

消息过期的死信队列测试

1
2
3
4
5
6
7
8
9
10
11
/**
* 过期消息投递到死信队列
* 投递到一个正常的队列,但是该队列有设置过期时间,到过期时间之后消息会被投递到死信交换机(队列)
*/
@Test
void dlxTTLMessageTest() {
rabbitTemplate.convertAndSend(
"my_normal_exchange",
"my_ttl_dlx",
"测试过期消息:6秒过期后会被投递到死信交换机");
}

测试结果:

未过期时:

未过期

过期后:

已过期

消息过长的死信队列测试

最早的那条会投递到死信队列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 消息长度超过2,会投递到死信队列中
*/
@Test
void dlxMaxMessageTest() {
rabbitTemplate.convertAndSend(
"my_normal_exchange",
"my_max_dlx",
"发送消息1:消息长度超过2,会被投递到死信队列中!");
rabbitTemplate.convertAndSend(
"my_normal_exchange",
"my_max_dlx",
"发送消息2:消息长度超过2,会被投递到死信队列中!");
rabbitTemplate.convertAndSend(
"my_normal_exchange",
"my_max_dlx",
"发送消息3:消息长度超过2,会被投递到死信队列中!");
}

测试结果:

整体:

整体

第一条进入死信队列:

第一条

流程

流程

最后更新: 2020年08月22日 15:33

原始链接: http://ligangit.com/2020/08/22/RabbitMQ-死信队列/

× 请我吃糖~
打赏二维码