前言

在说死信队列之前,我们先介绍下为什么需要用死信队列。

如果想直接了解死信对接,直接跳入下文的"死信队列"部分即可。

ack机制和requeue-rejected属性

在项目springboot-demo我们看到application.yaml文件部分配置内容如下

...

listener:

type: simple

simple:

acknowledge-mode: auto

concurrency: 5

default-requeue-rejected: true

max-concurrency: 100

...

其中

acknowledge-mode

该配置项是用来表示消息确认方式,其有三种配置方式,分别是none、manual和auto。

none意味着没有任何的应答会被发送。

manual意味着监听者必须通过调用Channel.basicAck()来告知所有的消息。

auto意味着容器会自动应答,除非MessageListener抛出异常,这是默认配置方式。

default-requeue-rejected

该配置项是决定由于监听器抛出异常而拒绝的消息是否被重新放回队列。默认值为true。

我一开始对于这个属性有个误解,我以为rejected是表示拒绝,所以将requeue-rejected连起来是拒绝重新放回队列,后来查了资料明白这个属性的功能才想起来rejected是个形容词,其表示的应该是被拒绝的消息

所以如果该属性配置为true表示会重新放回队列,如果配置为false表示不会放回队列。

下面我们看看acknowledge-mode参数和default-requeue-rejected参数使用不同的组合方式,RabbitMQ是如何处理消息的。

代码依然使用springboot-demo中的RabbitApplicationTests发送消息,使用Receiver类监听demo-queue队列的消息。

对于Receiver类添加了一行代码,该代码模拟抛出异常

@Component

public class Receiver {

@RabbitListener(queues = "demo_queue")

public void created(String message) {

System.out.println("orignal message: " + message);

int i = 1/0;

}

}

acknowledge-mode=none, default-requeue-rejected=false

该配置不会确认消息是否正常消费,所以在控制台没有抛出任何异常。通过在RabbitMQ管理页面也没有看到重新放回队列的消息

acknowledge-mode=none, default-requeue-rejected=true

同样该配置不会确认消息是否正常消费,所以在控制台没有抛出任何异常。而且即使default-requeue-rejected配置为true因为没有确认所以也没有看到重新放回队列的消息

acknowledge-mode=manual, default-requeue-rejected=false

该配置需要手动确认消息是否正常消费,但是代码中并没有手动确认,个人理解是因为没有收到ack,所以消息又回到了队列中。

acknowledge-mode=manual, default-requeue-rejected=true

该配置需要手动确认消息是否正常消费,但是代码中并没有手动确认,所以消息被重新放入到队列中了,并且在控制台发现还抛出了异常(这块不是很清楚,default-requeue-rejected设置true和false带来的不同效果,有了解的麻烦下方留言指教)。

acknowledge-mode=auto, default-requeue-rejected=false

该配置采用自动确认,从结果来看,是自动确认了。

从控制台打印的结果可以看出Receiver方法执行了3次,分别是前面两条放回队列的消息以及这次发送的消息,所以3条消息都消费了。

同时因为default-requeue-rejected设置为false,所以即使消费抛出异常,也没有将消息放回队列。

acknowledge-mode=auto, default-requeue-rejected=true

该配置同样采用自动确认,从结果看出,没有抛出异常(这块也不是很理解),且因为default-requeue-rejected设置为true,所以消息重新回到队列。

综上罗列这么多情况只为说明有些情况下,如果消息消费出错,因为配置问题导致消息丢失了。这在很多情况下是要命的,比如用户支付的订单号,如果因为抛异常等原因直接丢失是很要命的。

所以,我们需要有一个确保机制,能够保证即使失败的消息也能保存下来,这时候死信队列就排上用场了。

死信队列

死信队列的整个设计思路是这样的

生产者 --> 消息 --> 交换机 --> 队列 --> 变成死信 --> DLX交换机 -->队列 --> 消费者

下面我们通过网上的一个简单的死信队列的实现看看如何使用死信队列。

@Bean("deadLetterExchange")

public Exchange deadLetterExchange() {

return ExchangeBuilder.directExchange("DL_EXCHANGE").durable(true).build();

}

@Bean("deadLetterQueue")

public Queue deadLetterQueue() {

Map args = new HashMap<>(2);

// x-dead-letter-exchange 声明 死信交换机

args.put("x-dead-letter-exchange", "DL_EXCHANGE");

// x-dead-letter-routing-key 声明 死信路由键

args.put("x-dead-letter-routing-key", "KEY_R");

return QueueBuilder.durable("DL_QUEUE").withArguments(args).build();

}

@Bean("redirectQueue")

public Queue redirectQueue() {

return QueueBuilder.durable("REDIRECT_QUEUE").build();

}

/**

* 死信路由通过 DL_KEY 绑定键绑定到死信队列上.

*

* @return the binding

*/

@Bean

public Binding deadLetterBinding() {

return new Binding("DL_QUEUE", Binding.DestinationType.QUEUE, "DL_EXCHANGE", "DL_KEY", null);

}

/**

* 死信路由通过 KEY_R 绑定键绑定到死信队列上.

*

* @return the binding

*/

@Bean

public Binding redirectBinding() {

return new Binding("REDIRECT_QUEUE", Binding.DestinationType.QUEUE, "DL_EXCHANGE", "KEY_R", null);

}

注意

声明了一个direct模式的exchange。

声明了一个死信队列deadLetterQueue,该队列配置了一些属性x-dead-letter-exchange表明死信交换机,x-dead-letter-routing-key表明死信路由键,因为是direct模式,所以需要设置这个路由键。

声明了一个替补队列redirectQueue,变成死信的消息最终就是存放在这个队列的。

声明绑定关系,分别是死信队列以及替补队列和交换机的绑定。

那么如何模拟生成一个死信消息呢,可以在发送到DL_QUEUE的消息在10秒后失效,然后转发到替补队列中,代码实现如下

public void sendMsg(String content) {

CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString());

MessagePostProcessor messagePostProcessor = message -> {

MessageProperties messageProperties = message.getMessageProperties();

// 设置编码

messageProperties.setContentEncoding("utf-8");

// 设置过期时间10*1000毫秒

messageProperties.setExpiration("5000");

return message;

};

rabbitTemplate.convertAndSend("DL_EXCHANGE", "DL_KEY", content, messagePostProcessor);

}

执行结果如下

消息首先进入DL_QUEUE,5秒后失效,被转发到REDIRECT_QUEUE中。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

java死信队列_Spring Boot系列教程之死信队列详解相关推荐

  1. Spring Boot系列教程四:配置文件详解properties

    一.配置随机数,使用随机数 在application.properties文件添加配置信息 [html] view plaincopy #32位随机数 woniu.secret=${random.va ...

  2. async spring 默认线程池_Spring boot注解@Async线程池实例详解

    这篇文章主要介绍了Spring boot注解@Async线程池实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 从Spring3开始提供了@A ...

  3. java正则表达式 匹配次数_正则表达式教程之重复匹配详解

    本文实例讲述了正则表达式教程之重复匹配.分享给大家供大家参考,具体如下: 注:在所有例子中正则表达式匹配结果包含在源文本中的[和]之间,有的例子会使用Java来实现,如果是java本身正则表达式的用法 ...

  4. Cubemx与HAL库系列教程|系统时钟配置详解及源码分析

    STM32时钟系统简介 STM32种类繁多,时钟系统也不尽相同,但基本的还是大差不差,今日小飞哥就F1系列的MCU简单聊一聊STM32的时钟系统 1.时钟种类介绍: 先来看一看时钟树图,包含了整个系统 ...

  5. java不同环境_Spring Boot系列 – 5. 不同的环境使用不同的配置

    SpringBoot系列-5.不同的环境使用不同的配置数据库 spring boot中,可以通过在application.yml配置文件中,配置多个不同的profile, 实现在不同的环境(比如开发. ...

  6. java 事件监听应用_Spring Boot应用事件监听示例详解

    前言 本文主要给大家介绍了关于Spring Boot应用事件监听的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧 1. Spring Boot特有的应用事件 除了Spring ...

  7. java正则表达式匹配路径_正则表达式教程之位置匹配详解

    本文实例讲述了正则表达式教程之位置匹配.分享给大家供大家参考,具体如下: 注:在所有例子中正则表达式匹配结果包含在源文本中的[和]之间,有的例子会使用Java来实现,如果是java本身正则表达式的用法 ...

  8. 全网最详系列教程-nacos配置中心详解-NameSpace、Group、DataID

    特别喜欢李白的一句诗:俱怀逸兴壮思飞,欲上青天揽明月.其表达了对光明世界的执着追求.我亦身为三等码农,也向往着能够改变世界. 文章目录 1.命名空间.分组.DataID三者之间的关系 2.DataID ...

  9. [js高手之路] es6系列教程 - 迭代器与生成器详解

    什么是迭代器? 迭代器是一种特殊对象,这种对象具有以下特点: 1,所有对象都有一个next方法 2,每次调用next方法,都会返回一个对象,该对象包含两个属性,一个是value, 表示下一个将要返回的 ...

最新文章

  1. python初学者之网络爬虫_Python初学者之网络爬虫(二)
  2. 给技术人上的管理课:平衡和集中
  3. Linux的硬盘分区
  4. 从github下载项目并导入eclipse
  5. 自然语言12_Tokenizing Words and Sentences with NLTK
  6. 一个设计元素很多的网站
  7. 操作主机 RID matser
  8. ubuntu18重装笔记
  9. 国内2大Git代码托管网站
  10. 8a 中断 传感器采集_加速度传感器的安装,你get了吗
  11. 语音识别维特比解码_一种基于维特比算法的花洒语音识别系统及方法与流程
  12. 第11 章 关联容器
  13. 测试开发工程师面试题目
  14. 批量重命名图片,去除括号
  15. 建网站应该买什么云服务器,建网站应该买什么云服务器
  16. catia二次开发招标_CATIA二次开发
  17. 通过谷歌骇客语法搜索后台:_书评:我们的骇客并拥有
  18. 利用微信机器人 自动发送验证码
  19. U盘启动盘制作与ISO分享
  20. 领带的10种打法图解

热门文章

  1. iterm2 agnoster主题设置中的一些踩坑 2018.8
  2. 【Python3爬虫】微博用户爬虫
  3. npm 有用的一些全局包
  4. kubernetes资源管理
  5. PHP如何让apache支持.htaccess 解决Internal Server Error The server …错误
  6. Ubuntu 12.04下NFS安装配置图解
  7. @tap和@click的区别_计算属性---uview工作笔记001
  8. ES6新特性_ES6扩展运算符的介绍---JavaScript_ECMAScript_ES6-ES11新特性工作笔记013
  9. 微服务升级_SpringCloud Alibaba工作笔记0001---新一代网关spring gateway和zuul的关系说明
  10. Java的接口及实例(转)