1、死信队列

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

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

2、消息变成死信的情况

  • 消息被拒绝(Basic.Reject/Basic.Nack),并且设置 requeue 参数为false, requeue 表示是否重新入队
  • 消息过期
  • 队列达到最大长度(声明队列的时候设置 x-max-length 参数,表示队列最大长度)

3、死信队列设置

可以通过为队列设置 x-dead-letter-exchange 参数设置 DLX,也可以通过设置 x-dead-letter-routing-key 参数为这个DLX指定路由键,如果没有特殊指定,则使用原队列的路由键。

4、死信队列测试

4.1 测试过程

整个过程如下图:

  • 第一步:创建两个交换器 exchange.normal 和 exchange.dlx, 分别绑定两个队列 queue.normal 和 queue.dlx
  • 第二步:把 queue.normal 队列里面的消息配置过期时间,然后通过 x-dead-letter-exchange 指定死信交换器为 exchange.dlx
  • 第三步:发送消息到 queue.normal 中,消息过期之后流入 exchange.dlx,然后路由到 queue.dlx 队列中,然后进行消费

4.2 生产者代码

<?php
require __DIR__ . '/../../../../vendor/autoload.php'; use PhpAmqpLib\Wire\AMQPTable;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Exchange\AMQPExchangeType;
use PhpAmqpLib\Connection\AMQPStreamConnection; /**
* 死信队列测试
* 1、创建两个交换器 exchange.normal 和 exchange.dlx, 分别绑定两个队列 queue.normal 和 queue.dlx
* 2、把 queue.normal 队列里面的消息配置过期时间,然后通过 x-dead-letter-exchange 指定死信交换器为 exchange.dlx
* 3、发送消息到 queue.normal 中,消息过期之后流入 exchange.dlx,然后路由到 queue.dlx 队列中,进行消费
*/ // todo 更改配置
$connection = new AMQPStreamConnection('192.168.33.1', 5672, 'zhangcs', 'zhangcs', '/'); $channel = $connection->channel(); $channel->exchange_declare('exchange.dlx', AMQPExchangeType::DIRECT, false, true);
$channel->exchange_declare('exchange.normal', AMQPExchangeType::FANOUT, false, true);
$args = new AMQPTable();
// 消息过期方式:设置 queue.normal 队列中的消息10s之后过期
$args->set('x-message-ttl', 10000);
// 设置队列最大长度方式: x-max-length
//$args->set('x-max-length', 1);
$args->set('x-dead-letter-exchange', 'exchange.dlx');
$args->set('x-dead-letter-routing-key', 'routingkey');
$channel->queue_declare('queue.normal', false, true, false, false, false, $args);
$channel->queue_declare('queue.dlx', false, true, false, false); $channel->queue_bind('queue.normal', 'exchange.normal');
$channel->queue_bind('queue.dlx', 'exchange.dlx', 'routingkey');
$message = new AMQPMessage('Hello DLX Message');
$channel->basic_publish($message, 'exchange.normal', 'rk'); $channel->close();
$connection->close();

运行生产者代码之后,queue.normal 队列会有一条消息,如下图:

10秒之后,消息会过期,然后被进入 exchange.dlx, 进而路由到 queue.dlx 队列中:

4.3、消费者代码

<?php
require __DIR__ . '/../../../../vendor/autoload.php'; use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Exchange\AMQPExchangeType;
use PhpAmqpLib\Connection\AMQPStreamConnection; // todo 更改配置
$connection = new AMQPStreamConnection('192.168.33.1', 5672, 'zhangcs', 'zhangcs', '/');
$channel = $connection->channel(); $channel->exchange_declare('exchange.dlx', AMQPExchangeType::DIRECT, false, true);
$channel->queue_declare('queue.dlx', false, true, false, false); $channel->queue_bind('queue.dlx', 'exchange.dlx', 'routingkey'); function process_message($message)
{
echo "\n--------\n";
echo $message->body;
echo "\n--------\n";
$message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']);
} $channel->basic_consume('queue.dlx', 'consumer_tag', false, false, false, false, 'process_message'); function shutdown($channel, $connection)
{
$channel->close();
$connection->close();
}
register_shutdown_function('shutdown', $channel, $connection); while ($channel ->is_consuming()) {
$channel->wait();
}

运行消费者代码之后,消费会从 queue.dlx 中消费掉:

【RabbitMQ 实战指南】一 死信队列的更多相关文章

  1. 【RabbitMQ 实战指南】一 延迟队列

    1.什么是延迟队列 延迟队列中存储延迟消息,延迟消息是指当消息被发送到队列中不会立即消费,而是等待一段时间后再消费该消息. 延迟队列很多应用场景,一个典型的应用场景是订单未支付超时取消,用户下单之后3 ...

  2. 【RabbitMQ 实战指南】一 RabbitMQ 开发

    1.RabbitMQ 安装 RabbitMQ 的安装可以参考官方文档:https://www.rabbitmq.com/download.html 2.管理页面 rabbitmq-management ...

  3. 《RabbitMQ》什么是死信队列

    一 什么是死信队列 当一条消息在队列中出现以下三种情况的时候,该消息就会变成一条死信. 消息被拒绝(basic.reject / basic.nack),并且requeue = false 消息TTL ...

  4. .Net RabbitMQ实战指南——客户端开发

    开发中关键的Class和Interface有Channel.Connection.ConnectionFactory.Consumer等,与RabbitMQ相关的开发工作,基本上是围绕Connecti ...

  5. .Net RabbitMQ实战指南——进阶(一)

    备份交换器 备份交换器,英文名称为Alternate Exchange,简称AE.通过在声明交换器(调用channel.ExchangeDeclare方法)时添加alternate-exchange参 ...

  6. RabbitMQ延迟消息:死信队列 | 延迟插件 | 二合一用法+踩坑手记+最佳使用心得

    前言 前段时间写过一篇: # RabbitMQ:消息丢失 | 消息重复 | 消息积压的原因+解决方案+网上学不到的使用心得 很多人加了我好友,说很喜欢这篇文章,也问了我一些问题. 因为最近工作比较忙, ...

  7. 【RabbitMQ 实战指南】一 过期时间TTL

    RabbitMQ 可以对消息和队列设置过期时间(TTL) 1.设置消息的TTL 目前有两种方式可以设置消息的TTL 第一种方式是通过队列属性设置,队列中所有消息都有相同的过期时间 第二种方式是对消息本 ...

  8. .Net RabbitMQ实战指南——RabbitMQ相关概念介绍

    什么是消息中间件 消息(Message)是指在应用间传送的数据.消息可以非常简单,比如只包含文本字符串.JSON等,也可以很复杂,比如内嵌对象. 消息队列中间件(Message Queue Middl ...

  9. 【RabbitMQ 实战指南】一 RabbitMQ入门

    1.消息中间件 1.1.什么是消息中间件 消息中间件(Message Queue Middleware,简称 MQ)是指利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通道来进行分布式系 ...

随机推荐

  1. Python基础(十一)

    今日主要内容 补充:三目运算 f-strings 迭代器 生成器 补充:三目运算 三目运算(三元运算)结构: 表达式1 if 条件表达式 else 表达式2 c = a if a > b els ...

  2. HTML定位和布局----float浮动

    1.定位体系一共有三种 (1)常规流: (2)浮动定位 (3)绝对定位 2.float属性常用的语法: (1)float:left:左浮动 (2)float:right:右浮动 (3)float:no ...

  3. 【linux】【Fabric】Centos7搭建Fabric运行环境

    1.安装jdk1.8配置环境变量 参考:https://www.cnblogs.com/jxd283465/p/11541506.html 2.安装git yum -y install git 3.安 ...

  4. vs加调试代码的正确姿势

    为了方便,我们会在系统中加入一些调试代码,比如自动登录,这样会省掉很多精力时间,但用的姿势不对, 第一重姿势:打包注释 我看一些人在vs中加调试代码(比如自动登录),然后打包的时候注释掉,这样操作是省 ...

  5. mongodb 获取自增数

    mongodb db.getCollection('user').findAndModify({update:{$inc:{'level':1}},query:{"name":&q ...

  6. 基于操作系统原理的Linux的内存管理

    一.实验目的 1.理解虚拟内存.磁盘缓存的概念. 2.掌握基本的内存管理知识. 3.掌握查看实时查看内存.内存回收的方法 二.实验内容 1. 监控内存使用情况 2. 检查和回收内容 三.实验平台 1. ...

  7. 死磕 java同步系列之Phaser源码解析

    问题 (1)Phaser是什么? (2)Phaser具有哪些特性? (3)Phaser相对于CyclicBarrier和CountDownLatch的优势? 简介 Phaser,翻译为阶段,它适用于这 ...

  8. 【SQL server基础】object_id()函数

    在SQLServer数据库中,如果查询数据库中是否存在指定名称的索引或者外键约束等,经常会用到object_id('name','type')方法,做笔记如下: ? 语法:object_id('obj ...

  9. 使用java的循环单向链表解决约瑟夫问题

    什么是约瑟夫问题 据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定 ...

  10. Python sys.setdefaultencoding('utf-8') 后就没输出

    为了解决Python的 UnicodeDecodeError: 'ascii' codec can't decode byte ,我们可以加入以下代码. import sys reload(sys) ...