RabbitMQ消费端ACK与重回队列机制,TTL,死信队列详解(十一)
消费端的手工ACK和NACK
消费端进行消费的时候,如果由于业务异常我们可以进行日志的记录,然后进行补偿。
如果由于服务器宕机等严重问题,那么我们就需要手工进行ACK保障消费端成功。
消费端重回队列
为了对没有处理成功的消息,把消息重新回递给Broker。
一般我们在实际应用中,都会关闭重回队列,也就是设置为false。
- //生产端代码
- ConnectionFactory connectionFactory = new ConnectionFactory();
- connectionFactory.setHost("127.0.0.1");
- connectionFactory.setPort(5672);
- connectionFactory.setVirtualHost("/");
- Connection connection = connectionFactory.newConnection();
- Channel channel = connection.createChannel();
- String exchange = "test_ack_exchange";
- String routingKey = "ack.save";
- for(int i =0; i<5; i ++){
- Map<String, Object> headers = new HashMap<String, Object>();
- headers.put("num", i);
- AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
- .deliveryMode(2)
- .contentEncoding("UTF-8")
- .headers(headers)
- .build();
- String msg = "Hello RabbitMQ ACK Message " + i;
- channel.basicPublish(exchange, routingKey, true, properties, msg.getBytes());
- }
- //消费端代码
- ConnectionFactory connectionFactory = new ConnectionFactory();
- connectionFactory.setHost("127.0.0.1");
- connectionFactory.setPort(5672);
- connectionFactory.setVirtualHost("/");
- Connection connection = connectionFactory.newConnection();
- Channel channel = connection.createChannel();
- String exchangeName = "test_ack_exchange";
- String queueName = "test_ack_queue";
- String routingKey = "ack.#";
- channel.exchangeDeclare(exchangeName, "topic", true, false, null);
- channel.queueDeclare(queueName, true, false, false, null);
- channel.queueBind(queueName, exchangeName, routingKey);
- // 手工签收 必须要关闭 autoAck = false
- channel.basicConsume(queueName, false, new MyConsumer(channel));
- //自定义消费者
- private Channel channel ;
- public MyConsumer(Channel channel) {
- super(channel);
- this.channel = channel;
- }
- @Override
- public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
- System.err.println("-----------consume message----------");
- System.err.println("body: " + new String(body));
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- if((Integer)properties.getHeaders().get("num") == 0) {
- channel.basicNack(envelope.getDeliveryTag(), false, true);
- } else {
- channel.basicAck(envelope.getDeliveryTag(), false);
- }
- }
TTL队列/消息
TTL是time to live的缩写,也就是生存时间
RabbitMQ支持消息的过期时间,在消息发送时可以进行指定
RabbitMQ支持队列的过期时间,从消息入队列开始计算,只要超过了队列的超过时间配置,那么消息会自动的清除。
消息10s过期,TTL是队列过期时间。
DLX死信队列
DLX,Dead-Letter-Exchange
利用DLX,当消息在一个队列中变成死信之后,它能够被重新publish到另一个exchange,这个exchange就是DLX。
消息变成死信情况:
消息被拒绝(basic.reject/basic.nack)并且request=false
消息TTL过期
队列达到最大的长度
DLX也是一个正常的exchange,和一般的exchange没有区别,他能在任何的队列上被指定,实际上就是设置某个队列的属性。
当这个队列中有死信时,RabbitMQ就会自动的将这个消息重新发布到设置的exchange上去,进而被路由到另一个队列。
可以监听这个队列中消息做相应的处理,这个特性可以弥补RabbitMQ3.0以前支持的immediate参数的功能。
死信队列设置:
首先要设置死信队列的exchange和queue,然后进行绑定:
Exchange:dlx.exchange
Queue:dlx.queue
RoutingKey:#
然后我们进行正常声明交换机,队列,绑定,只不过我们需要在队列加上一个参数:arguments.put("x-dead-letter-exchange","dlx.exchange");
这样消息在过期、request、队列子啊达到最大长度时, 消息就可以直接路由到死信队列。
- //生产者端代码
- ConnectionFactory connectionFactory = new ConnectionFactory();
- connectionFactory.setHost("127.0.0.1");
- connectionFactory.setPort(5672);
- connectionFactory.setVirtualHost("/");
- Connection connection = connectionFactory.newConnection();
- Channel channel = connection.createChannel();
- String exchange = "test_dlx_exchange";
- String routingKey = "dlx.save";
- String msg = "Hello RabbitMQ DLX Message";
- for(int i =0; i<1; i ++){
- AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
- .deliveryMode(2)
- .contentEncoding("UTF-8")
- .expiration("10000")
- .build();
- channel.basicPublish(exchange, routingKey, true, properties, msg.getBytes());
- }
- //消费者端代码
- ConnectionFactory connectionFactory = new ConnectionFactory();
- connectionFactory.setHost("127.0.0.1");
- connectionFactory.setPort(5672);
- connectionFactory.setVirtualHost("/");
- Connection connection = connectionFactory.newConnection();
- 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> agruments = new HashMap<String, Object>();
- agruments.put("x-dead-letter-exchange", "dlx.exchange");
- //这个agruments属性,要设置到声明队列上
- channel.queueDeclare(queueName, true, false, false, agruments);
- 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", "#");
- channel.basicConsume(queueName, true, new MyConsumer(channel));
- //自定义消费者
- public MyConsumer(Channel channel) {
- super(channel);
- }
- @Override
- public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
- System.err.println("-----------consume message----------");
- System.err.println("consumerTag: " + consumerTag);
- System.err.println("envelope: " + envelope);
- System.err.println("properties: " + properties);
- System.err.println("body: " + new String(body));
- }
RabbitMQ消费端ACK与重回队列机制,TTL,死信队列详解(十一)的更多相关文章
- 消费端ACK和重回队列
使用场景 消费端ACK和重回队列 消费端ACK使用场景: 1.消费端进行消费的时候,如果由于业务异常我们可以进行日志记录,然后进行补偿. 2.由于服务器宕机等严重问题,那我们就需要手工进行ACK保障消 ...
- RabbitMQ 消费端限流、TTL、死信队列
目录 消费端限流 1. 为什么要对消费端限流 2.限流的 api 讲解 3.如何对消费端进行限流 TTL 1.消息的 TTL 2.队列的 TTL 死信队列 实现死信队列步骤 总结 消费端限流 1. 为 ...
- RabbitMQ 入门系列:9、扩展内容:死信队列:真不适合当延时队列。
系列目录 RabbitMQ 入门系列:1.MQ的应用场景的选择与RabbitMQ安装. RabbitMQ 入门系列:2.基础含义:链接.通道.队列.交换机. RabbitMQ 入门系列:3.基础含义: ...
- python中利用队列asyncio.Queue进行通讯详解
python中利用队列asyncio.Queue进行通讯详解 本文主要给大家介绍了关于python用队列asyncio.Queue通讯的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细 ...
- 服务端捡起或丢弃指定物品ID触发详解
传奇服务端捡起或丢弃指定物品ID触发详解: @PickUpItemsX X是物品数据库中对应的IDX@DropItemsX X是物品数据库中对应的IDX@H.PickUpItemsX X是物品数据库中 ...
- RabbitMQ消费端消息的获取方式(.Net Core)
1[短链接]:BasicGet(String queue, Boolean autoAck) 通过request的方式独自去获取消息,断开式,一次次获取,如果返回null,则说明队列中没有消息. 隐患 ...
- RabbitMQ消费端限流策略(十)
消费端限流: 什么是消费端限流? 场景: 我们RabbitMQ服务器有上万条未处理的消息,我们随便打开一个消费者客户端,会出现下面情况: 巨量的消息瞬间全部推送过来,但是我们单个客户端无法同时处理这么 ...
- RabbitMQ消费端自定义监听(九)
场景: 我们一般在代码中编写while循环,进行consumer.nextDelivery方法进行获取下一条消息,然后进行消费处理. 实际环境: 我们使用自定义的Consumer更加的方便,解耦性更强 ...
- RabbitMQ与.net core(四) 消息的优先级 与 死信队列
1.消息的优先级 假如现在有个需求,我们需要让一些优先级最高的通知推送到客户端,我们可以使用redis的sortedset,也可以使用我们今天要说的rabbit的消息优先级属性 Producer代码 ...
随机推荐
- vue2.0父子组件通信以及同级组件通信
1.父向子通信 父组件为singer.vue.子组件为list-view.vue.需要把歌手的数据传给子组件.则绑定 :data = 'singers' ,singers为父组件的值.data为子组件 ...
- js if 判断的使用
!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> ...
- mock.js的运用
一:概念 Mock.js是一款模拟数据生成器,旨在帮助前端攻城师独立于后端进行开发,帮助编写单元测试.提供了以下模拟功能: 根据数据模板生成模拟数据 模拟 Ajax 请求,生成并返回模拟数据 基于 H ...
- JAVA基础--JAVA 集合框架(泛型、file类)
一.集合总结 集合:Collection体系.Map体系. Collection体系:单列集合的共性操作规则. List:列表,可以重复,有下标,拥有特有的迭代器ListIterator. Array ...
- 线性表源码分享(c++),包含顺序表、单链表、循环链表、双向链表
---恢复内容开始--- 我是一个c++和数据结构的初学者,本文主要是把清华大学出版社的数据结构(用面向对象方法与c++语言描述)(第2版)这本书中第二章线性表的源码抄下来,在学习的过程中有助于加深印 ...
- c++多线程并发学习笔记(1)
共享数据带来的问题:条件竞争 避免恶性条件竞争的方法: 1. 对数据结构采用某种保护机制,确保只有进行修改的线程才能看到修改时的中间状态.从其他访问线程的角度来看,修改不是已经完成了,就是还没开始. ...
- Python 入门之编码
Python 入门之编码 1.编码初识: (1)ASCII码 :256 个 英文1个字节,不支持中文 (2)GBK(国标) : 英文1个字节 中文两个字节 (3)unicode (万国码):英文4个字 ...
- numpy.random.randn()和numpy.random.rand()
1 numpy.random.rand() (1)numpy.random.rand(d0,d1,…,dn) rand函数根据给定维度生成[0,1)之间的数据,包含0,不包含1 dn表格每个维度 返回 ...
- intellij idea 的快捷键方法
1.Ctrl+N按名字搜索类 相当于eclipse的ctrl+shift+R,输入类名可以定位到这个类文件,就像idea在其它的搜索部分的表现一样,搜索类名也能对你所要搜索的内容多个部分进行匹配,而且 ...
- gradle上sourceSets配置&同名文件合并问题
gradle的sourceSets可以对不同的buildType, productFlavor,buildVariant设置不同的文件路径,进行多样化处理. sourceSets{ main{ man ...