Config:

  1. import java.util.HashMap;
  2. import java.util.Map;
  3.  
  4. import org.springframework.amqp.core.Binding;
  5. import org.springframework.amqp.core.BindingBuilder;
  6. import org.springframework.amqp.core.DirectExchange;
  7. import org.springframework.amqp.core.FanoutExchange;
  8. import org.springframework.amqp.core.Queue;
  9. import org.springframework.context.annotation.Bean;
  10. import org.springframework.stereotype.Component;
  11.  
  12. //Fanout 类型 发布订阅模式
  13. @Component
  14. public class FanoutConfig {
  15.  
  16. /**
  17. * 定义死信队列相关信息
  18. */
  19. public final static String deadQueueName = "dead_queue";
  20. public final static String deadRoutingKey = "dead_routing_key";
  21. public final static String deadExchangeName = "dead_exchange";
  22. /**
  23. * 死信队列 交换机标识符
  24. */
  25. public static final String DEAD_LETTER_QUEUE_KEY = "x-dead-letter-exchange";
  26. /**
  27. * 死信队列交换机绑定键标识符
  28. */
  29. public static final String DEAD_LETTER_ROUTING_KEY = "x-dead-letter-routing-key";
  30.  
  31. // 邮件队列
  32. private String FANOUT_EMAIL_QUEUE = "fanout_email_queue";
  33.  
  34. // 短信队列
  35. private String FANOUT_SMS_QUEUE = "fanout_sms_queue";
  36. // fanout 交换机
  37. private String EXCHANGE_NAME = "fanoutExchange";
  38.  
  39. // 1.定义邮件队列
  40. @Bean
  41. public Queue fanOutEamilQueue() {
  42. // 将普通队列绑定到死信队列交换机上
  43. Map<String, Object> args = new HashMap<>(2);
  44. args.put(DEAD_LETTER_QUEUE_KEY, deadExchangeName);
  45. args.put(DEAD_LETTER_ROUTING_KEY, deadRoutingKey);
  46. Queue queue = new Queue(FANOUT_EMAIL_QUEUE, true, false, false, args);
  47. return queue;
  48. }
  49.  
  50. // 2.定义短信队列
  51. @Bean
  52. public Queue fanOutSmsQueue() {
  53. return new Queue(FANOUT_SMS_QUEUE);
  54. }
  55.  
  56. // 2.定义交换机
  57. @Bean
  58. FanoutExchange fanoutExchange() {
  59. return new FanoutExchange(EXCHANGE_NAME);
  60. }
  61.  
  62. // 3.队列与交换机绑定邮件队列
  63. @Bean
  64. Binding bindingExchangeEamil(Queue fanOutEamilQueue, FanoutExchange fanoutExchange) {
  65. return BindingBuilder.bind(fanOutEamilQueue).to(fanoutExchange);
  66. }
  67.  
  68. // 4.队列与交换机绑定短信队列
  69. @Bean
  70. Binding bindingExchangeSms(Queue fanOutSmsQueue, FanoutExchange fanoutExchange) {
  71. return BindingBuilder.bind(fanOutSmsQueue).to(fanoutExchange);
  72. }
  73.  
  74. /**
  75. * 创建配置死信邮件队列
  76. *
  77. * @return
  78. */
  79. @Bean
  80. public Queue deadQueue() {
  81. Queue queue = new Queue(deadQueueName, true);
  82. return queue;
  83. }
  84. /*
  85. * 创建死信交换机
  86. */
  87. @Bean
  88. public DirectExchange deadExchange() {
  89. return new DirectExchange(deadExchangeName);
  90. }
  91. /*
  92. * 死信队列与死信交换机绑定
  93. */
  94. @Bean
  95. public Binding bindingDeadExchange(Queue deadQueue, DirectExchange deadExchange) {
  96. return BindingBuilder.bind(deadQueue).to(deadExchange).with(deadRoutingKey);
  97. }
  98.  
  99. }

生产者  timestamp 设置为0

  1. package com.itmayiedu.rabbitmq;
  2.  
  3. import java.util.UUID;
  4.  
  5. import org.springframework.amqp.core.AmqpTemplate;
  6. import org.springframework.amqp.core.Message;
  7. import org.springframework.amqp.core.MessageBuilder;
  8. import org.springframework.amqp.core.MessageProperties;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.stereotype.Component;
  11.  
  12. import com.alibaba.fastjson.JSONObject;
  13.  
  14. @Component
  15. public class FanoutProducer {
  16. @Autowired
  17. private AmqpTemplate amqpTemplate;
  18.  
  19. public void send(String queueName) {
  20. JSONObject jsonObject = new JSONObject();
  21. jsonObject.put("email", "xx@163.com");
  22. jsonObject.put("timestamp", 0);
  23. String jsonString = jsonObject.toJSONString();
  24. System.out.println("jsonString:" + jsonString);
  25. // 设置消息唯一id 保证每次重试消息id唯一
  26. Message message = MessageBuilder.withBody(jsonString.getBytes())
  27. .setContentType(MessageProperties.CONTENT_TYPE_JSON).setContentEncoding("utf-8")
  28. .setMessageId(UUID.randomUUID() + "").build(); //消息id设置在请求头里面 用UUID做全局ID
  29. amqpTemplate.convertAndSend(queueName, message);
  30. }
  31. }

此时的消费者:

  1. @RabbitListener(queues = "fanout_email_queue")
  2. public void process(Message message, @Headers Map<String, Object> headers, Channel channel) throws Exception {
  3. // 获取消息Id
  4. String messageId = message.getMessageProperties().getMessageId();
  5. String msg = new String(message.getBody(), "UTF-8");
  6. System.out.println("邮件消费者获取生产者消息msg:"+msg+",消息id"+messageId);
  7.  
  8. JSONObject jsonObject = JSONObject.parseObject(msg);
  9. Integer timestamp = jsonObject.getInteger("timestamp");
  10.  
  11. try {
  12. int result = 1/timestamp;
  13. System.out.println("result"+result);
  14. // // 手动ack
  15. Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
  16. // 手动签收
  17. channel.basicAck(deliveryTag, false);
  18. } catch (Exception e) {
  19. //拒绝消费消息(丢失消息) 给死信队列
  20. channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
  21. }
  22.  
  23. System.out.println("执行结束....");
  24. }

异常状况:

添加死信队列的消费者,并启动后:

  1. package com.itmayiedu.rabbitmq;
  2.  
  3. import java.util.Map;
  4.  
  5. import org.springframework.amqp.core.Message;
  6. import org.springframework.amqp.rabbit.annotation.RabbitListener;
  7. import org.springframework.amqp.support.AmqpHeaders;
  8. import org.springframework.messaging.handler.annotation.Headers;
  9. import org.springframework.stereotype.Component;
  10.  
  11. import com.rabbitmq.client.Channel;
  12.  
  13. //死信队列
  14. @Component
  15. public class FanoutDeadEamilConsumer {
  16.  
  17. @RabbitListener(queues = "dead_queue")
  18. public void process(Message message, @Headers Map<String, Object> headers, Channel channel) throws Exception {
  19. // 获取消息Id
  20. String messageId = message.getMessageProperties().getMessageId();
  21. String msg = new String(message.getBody(), "UTF-8");
  22. System.out.println("死信邮件消费者获取生产者消息msg:"+msg+",消息id"+messageId);
  23. // // 手动ack
  24. Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
  25. // 手动签收
  26. channel.basicAck(deliveryTag, false);
  27.  
  28. System.out.println("执行结束....");
  29. }
  30.  
  31. }

RabbitMQ死信队列的更多相关文章

  1. RabbitMQ死信队列另类用法之复合死信

    前言 在业务开发过程中,我们常常需要做一些定时任务,这些任务一般用来做监控或者清理任务,比如在订单的业务场景中,用户在创建订单后一段时间内,没有完成支付,系统将自动取消该订单,并将库存返回到商品中,又 ...

  2. rabbitmq死信队列消息监听

    #邮件通知并发送队列消息#!/bin/bash maillog="/var/log/mq.maillog" message_file="/tmp/mq_message&q ...

  3. RabbitMQ 死信队列 延时

    package com.hs.services.config; import java.util.HashMap; import java.util.Map; import org.springfra ...

  4. 【RabbitMQ】一文带你搞定RabbitMQ死信队列

    本文口味:爆炒鱿鱼   预计阅读:15分钟 一.说明 RabbitMQ是流行的开源消息队列系统,使用erlang语言开发,由于其社区活跃度高,维护更新较快,性能稳定,深得很多企业的欢心(当然,也包括我 ...

  5. springboot rabbitmq 死信队列应用场景和完整demo

    何为死信队列? 死信队列实际上就是,当我们的业务队列处理失败(比如抛异常并且达到了retry的上限),就会将消息重新投递到另一个Exchange(Dead Letter Exchanges),该Exc ...

  6. 【MQ中间件】RabbitMQ -- RabbitMQ死信队列及内存监控(4)

    1.RabbitMQ TTL及死信队列 1.1.TTL概述 过期时间TTL表示可以对消息设置预期的时间,在这个时间内都可以被消费者接收获取:过了之后消息将自动被删除.RabbitMQ可以对消息和队列设 ...

  7. rabbitmq死信队列和延时队列的使用

    死信队列&死信交换器:DLX 全称(Dead-Letter-Exchange),称之为死信交换器,当消息变成一个死信之后,如果这个消息所在的队列存在x-dead-letter-exchange ...

  8. .Net Core&RabbitMQ死信队列

    过期时间 RabbitMQ可以为消息和队列设置过期时间Time To Live(TTL).其目的即过期. 消息过期时间 消息存储在队列中时,如果想为其设置一个有限的生命周期,而不是一直存储着,可以为其 ...

  9. RabbitMq死信队列(接盘侠)

    队列创建之后,后期对其修改或者参数添加会报错.需要把队列重新删除,重新创建线上环境不能把队列删除,优雅安全的方式是重新建一个队列,把死信队列相关的队列进行绑定 在有过期时间的队列中设定最大接收能力5条 ...

随机推荐

  1. PHP基础面试题(1-10)

    1.什么是PHP? PHP是一个基于服务端来创建动态网站的脚本语言,可以通过PHP和HTML 生成网站主页. 2.什么是面向对象?主要特征是什么? 面向对象是程序的一种设计方式,利于提高程序的重用性, ...

  2. php读取xml的神器

    <?xml version="1.0 encoding="UTF-8"?> <humans> <zhangying> <name ...

  3. Android开发:《Gradle Recipes for Android》阅读笔记1.3

    想命令行执行gradle的构建,可以通过提供的gradle wrapper或者安装gradle. 构建android项目不需要安装gradle,因为android studio已经包含gradle.& ...

  4. 回溯法——n后问题

    问题描述: 在n*n的棋盘上放置彼此不受攻击的n个皇后.按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子.n后问题等价于在n*n格的棋盘上放置n个皇后,任何2个皇后不放在同一行 ...

  5. 启发式搜索技术A*

    开篇 这篇文章介绍找最短路径的一种算法,它的字我比较喜欢:启发式搜索. 对于入门的好文章不多,而这篇文章就是为初学者而写的,很适合入门的一篇.文章定位:非专业性A*文章,很适合入门. 有图有真相,先给 ...

  6. EasyNVR智能云终端接入AI视频智能分析功能,用户可自定义接入自己的分析算法

    视频分析的需求 人工智能的发展和在行业中的作用就不用多说了,已经到了势在必行的一个程度了,尤其是对于流媒体音视频行业来说,这基本上是人工智能重中之重的领域,视频人工智能,也就是视频视觉分析的应用方式大 ...

  7. TFS二次开发-基线文件管理器(3)-源码文件的读取

    TFS登录成功后,就可以开始读取源码目录树了. 一般来说,我不建议将整个树全部读取出来,因为这里不光存有项目文件,还有项目源码.如果全部读取出会是非常大的一棵树.因此我建议只读出根目录,每一次点击打开 ...

  8. _utf8_encode _utf8_decode base64_encode base64_decode

    const Base64 = { // private property _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv ...

  9. MySQL事件的先后

    今天闲聊之时 提及MySQL事件的执行,发现一些自己之前没有注意的细节 如果在执行事件过程中,如果insert的存储过程发生意外 会如何 USE iot2; CREATE TABLE aaaa (ti ...

  10. ReentrantLock VS synchronized

    ReentrantLock 类实现了 Lock ,它拥有与 synchronized 相同的并发性和内存语义,但是添加了类似锁投票.定时锁等候和可中断锁等候的一些特性. 此外,它还提供了在激烈争用情况 ...