RabbitMQ TTL、死信队列
TTL概念
TTL是Time To Live的缩写,也就是生存时间。
RabbitMQ支持消息的过期时间,在消息发送时可以进行指定。
RabbitMQ支持队列的过期时间,从消息入队列开始计算,只要超过了队列的超时时间配置,那么消息会自动的清除。
这与 Redis 中的过期时间概念类似。我们应该合理使用 TTL 技术,可以有效的处理过期垃圾消息,从而降低服务器的负载,最大化的发挥服务器的性能。
TTL是Time To Live的缩写,也就是生存时间。RabbitMQ支持消息的过期时间,在消息发送时可以进行指定。
RabbitMQ支持队列的过期时间,从消息入队列开始计算,只要超过了队列的超时时间配置,那么消息会自动的清除。
这与 Redis 中的过期时间概念类似。我们应该合理使用 TTL 技术,可以有效的处理过期垃圾消息,从而降低服务器的负载,最大化的发挥服务器的性能。
RabbitMQ allows you to set TTL (time to live) for both messages and queues. This can be done using optional queue arguments or policies (the latter option is recommended). Message TTL can be enforced for a single queue, a group of queues or applied for individual messages.
RabbitMQ允许您为消息和队列设置TTL(生存时间)。 这可以使用可选的队列参数或策略来完成(建议使用后一个选项)。 可以对单个队列,一组队列强制执行消息TTL,也可以为单个消息应用消息TTL。
——摘自 RabbitMQ 官方文档
1.消息的 TTL
我们在生产端发送消息的时候可以在 properties 中指定 expiration属性来对消息过期时间进行设置,单位为毫秒(ms)。
/**
* deliverMode 设置为 2 的时候代表持久化消息
* expiration 意思是设置消息的有效期,超过10秒没有被消费者接收后会被自动删除
* headers 自定义的一些属性
* */
//5. 发送
Map<String, Object> headers = new HashMap<String, Object>();
headers.put("myhead1", "111");
headers.put("myhead2", "222");
AMQP.BasicProperties properties = new AMQP.BasicProperties().builder()
.deliveryMode(2)
.contentEncoding("UTF-8")
.expiration("100000")
.headers(headers)
.build();
String msg = "test message";
channel.basicPublish("", queueName, properties, msg.getBytes());
我们也可以后台管理页面中进入 Exchange 发送消息指定expiration

2.队列的 TTL
队列属性:x-message-ttl
可以控制被publish到queue中的message 被丢弃前能够存活的时间
我们也可以在后台管理界面中新增一个 queue,创建时可以设置 ttl,对于队列中超过该时间的消息将会被移除。
//Java代码:message在该queue的存过时间最大为60秒
Map<String, Object> args = new HashMap<String, Object>();
args.put("x-message-ttl", 60000);
channel.queueDeclare("myqueue", false, false, false, args);
死信队列
死信队列:没有被及时消费的消息存放的队列
消息没有被及时消费的原因:
a.消息被拒绝(basic.reject/ basic.nack)并且不再重新投递 requeue=false
b.TTL(time-to-live) 消息超时未消费
c.达到最大队列长度
1.DLX也是一个正常的Exchange,和一般的Exchange没有区别,它能在任何队列上被指定,实际上就是设置某个队列的属性
2.当这个队列中有死信时,RabbitMQ就会自动将这个消息重新发布到设置的Exchange上去,进而被路由到另一个队列
3.可以监听这个队列的消息做相应的处理,这个特性可以弥补RabbitMQ3.0以前支持的immediate参数的功能。
实现死信队列步骤
首先需要设置死信队列的 exchange 和 queue,然后进行绑定:
Exchange: dlx.exchange
Queue: dlx.queue
RoutingKey: # 代表接收所有路由 key- 然后我们进行正常声明交换机、队列、绑定,只不过我们需要在普通队列加上一个参数即可:
arguments.put("x-dead-letter-exchange",' dlx.exchange' ) 这样消息在过期、requeue失败、 队列在达到最大长度时,消息就可以直接路由到死信队列!
创建生产者
package com.dwz.rabbitmq.dlx; import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException; import com.dwz.rabbitmq.util.ConnectionUtils;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection; public class Producer {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtils.getConnection();
Channel channel = connection.createChannel(); String exchangeName = "test_dlx_exchange";
String routingkey = "dlx.save"; for(int i = 0; i < 1; i++) {
String msg = "Hello rabbitmq dlc-"+i+" message!"; Map<String, Object> headers = new HashMap<>();
headers.put("num", i);
AMQP.BasicProperties properties = new AMQP.BasicProperties().builder()
.deliveryMode(2)
.contentEncoding("utf-8")
.expiration("10000")
.headers(headers)
.build();
channel.basicPublish(exchangeName, routingkey, properties, msg.getBytes());
} channel.close();
connection.close();
}
}
创建消费者
package com.dwz.rabbitmq.dlx; import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException; import com.dwz.rabbitmq.util.ConnectionUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.rabbitmq.client.AMQP.BasicProperties; public class Consumer {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtils.getConnection();
Channel channel = connection.createChannel(); String exchangeName = "test_dlx_exchange";
String routingkey = "dlx.#";
String queueName = "test_dlx_queue"; //这是一个普通的交换机、队列和路由
channel.exchangeDeclare(exchangeName, "topic", true, false, null);
Map<String, Object> arguments = new HashMap<>();
arguments.put("x-dead-letter-exchange", "dlx.exchange");
channel.queueDeclare(queueName, true, false, false, arguments);
channel.queueBind(queueName, exchangeName, routingkey); channel.exchangeDeclare("dlx.exchange", "topic", true, false, null);
channel.queueDeclare("dlx.queue", true, false, false, null);
channel.queueBind("dlx.queue", "dlx.exchange", "#"); DefaultConsumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body); try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} System.out.println("消费端:" + new String(body));
channel.basicAck(envelope.getDeliveryTag(), false);
}
}; //手工签收必须关闭autoAck设置为false
channel.basicConsume(queueName, false, consumer);
}
}
测试步骤
1.先启动consumer,在管控平台上看到test_dlx_exchange、test_dlx_queue和dlx.exchange、dlx.queue都创建完成然后停止consumer。
2.启动producer,10秒钟前发现消息在普通队列test_dlx_queue中,10秒钟后发现消息出现在死信队列dlx.queue中。
总结
DLX也是一个正常的 Exchange,和一般的 Exchange 没有区别,它能在任何的队列上被指定,实际上就是设置某个队列的属性。当这个队列中有死信时,RabbitMQ 就会自动的将这个消息重新发布到设置的DLX Exchange 上去,进而被路由到另一个队列。可以监听这个队列中消息做相应的处理。
相关文章
RabbitMQ Queue中Arguments属性参数过期队列,过期消息,超时队列的声明
RabbitMQ TTL、死信队列的更多相关文章
- RabbitMQ实战-死信队列
RabbitMQ死信队列 场景说明 代码实现 简单的Util 生产者 消费者 场景说明 场景: 当队列的消息未正常被消费时,如何解决? 消息被拒绝并且不再重新投递 消息超过有效期 队列超载 方案: 未 ...
- RabbitMQ配置死信队列
死信队列 消息传输过程中难免会产生一些无法及时处理的消息,这些暂时无法处理的消息有时候也是需要被保留下来的,于是这些无法被及时处理的消息就变成了死信. 既然需要保留这些死信,那么就需要一个容器来存储它 ...
- RabbitMQ之死信队列
1:何为死信队列 死信队列也是一个正常的队列,可以被消费. 但是,死信队列的消息来源于其他队列的转发. 2:如何触发死信队列 1:消息超时 2:队列长度达到极限 3:消息被拒绝消费,并不再重进队列,且 ...
- RabbitMQ 消费端限流、TTL、死信队列
目录 消费端限流 1. 为什么要对消费端限流 2.限流的 api 讲解 3.如何对消费端进行限流 TTL 1.消息的 TTL 2.队列的 TTL 死信队列 实现死信队列步骤 总结 消费端限流 1. 为 ...
- 【RabbitMQ】一文带你搞定RabbitMQ死信队列
本文口味:爆炒鱿鱼 预计阅读:15分钟 一.说明 RabbitMQ是流行的开源消息队列系统,使用erlang语言开发,由于其社区活跃度高,维护更新较快,性能稳定,深得很多企业的欢心(当然,也包括我 ...
- 面试官:RabbitMQ过期时间设置、死信队列、延时队列怎么设计?
哈喽!大家好,我是小奇,一位不靠谱的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新 一.前言 RabbitMQ我们经常的使用, ...
- RabbitMQ死信队列另类用法之复合死信
前言 在业务开发过程中,我们常常需要做一些定时任务,这些任务一般用来做监控或者清理任务,比如在订单的业务场景中,用户在创建订单后一段时间内,没有完成支付,系统将自动取消该订单,并将库存返回到商品中,又 ...
- rabbitmq~消息失败后重试达到 TTL放到死信队列(事务型消息补偿机制)
这是一个基于消息的分布式事务的一部分,主要通过消息来实现,生产者把消息发到队列后,由消费方去执行剩下的逻辑,而当消费方处理失败后,我们需要进行重试,即为了最现数据的最终一致性,在rabbitmq里,它 ...
- RabbitMQ消费端ACK与重回队列机制,TTL,死信队列详解(十一)
消费端的手工ACK和NACK 消费端进行消费的时候,如果由于业务异常我们可以进行日志的记录,然后进行补偿. 如果由于服务器宕机等严重问题,那么我们就需要手工进行ACK保障消费端成功. 消费端重回队列 ...
随机推荐
- spark学习之Lambda架构日志分析流水线
单机运行 一.环境准备 Flume 1.6.0 Hadoop 2.6.0 Spark 1.6.0 Java version 1.8.0_73 Kafka 2.11-0.9.0.1 zookeeper ...
- python爬取妹子图全站全部图片-可自行添加-线程-进程爬取,图片去重
from bs4 import BeautifulSoupimport sys,os,requests,pymongo,timefrom lxml import etreedef get_fenlei ...
- Python实现读取Excel文档中的配置并下载软件包
问题:现在遇到这样一个问题,服务器存储了很多软件包,这些包输入不同的产品,每个产品都有自己的配置,互相交叉,那么到底某一产品所有配置的软件包下载后,占用多大空间呢? 分析:从这个问题入手,了解到:软件 ...
- 微信小程序开发(一)创建一个小程序Hello World!
开发微信小程序并不是很难,网上有很多小程序开发资料,尤其是微信官方的<小程序开发指南>最详细. 下面是我开发小程序的历程: 第一步,请前往https://mp.weixin.qq.com/ ...
- Rsync+Sersync实时同步数据目录
第1章 Rsync简介 1.1 Rsync基本概述 rsync是一款开源的备份工具,可以在不同主机之间进行同步,可实现全量备份与增量备份 全量:将全部数据,进行传输覆盖 增量:只传输差异部分的数据 1 ...
- Linux:fdisk
fdisk [-l] 装置名称 选项与参数: -l:输入后面接的装置所有的partition内容.若仅有fdisk -l时,则系统将会把整个系统内能够搜寻到的装置的partition均列出来 fdis ...
- Tomcat控制台日志输出到本地文件
记事本打开startup.bat文件,修改如下内容 “call “%EXECUTABLE%” start %CMD_LINE_ARGS%” 改为 call "%EXECUTABLE%&quo ...
- 转 shell中的多进程【并发】
原文地址https://bbs.51cto.com/thread-1104907-1-1.html 根据我个人的理解, 所谓的多进程 只不过是将多个任务放到后台执行而已,很多人都用到过,所以现在讲的主 ...
- 计划任务 at,cron
示例:每3小时echo和wall命令
- 函数参数-arguments-reset参数
1.JS中用:arguments 1)存放实参的集合,是一个类似于数组的对象,只有数组的 length,没有数组方法 function add1(a,b,c) { console.log(argume ...