RabbitMQ进阶使用-延时队列的配置(Spring Boot)
依赖
- MAVEN配置pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
- Gradle配置build.gradle
compile('org.springframework.boot:spring-boot-starter-amqp')
连接配置
得益于spring boot的约定大于配置,只需要在application.yml加入下面配置即可。
spring:
rabbitmq:
host: host
port: port
username: admin
password: passwd
简单自定义RabbitTemplate和Queue配置
默认的配置还是略显不足,增加序列化配置如下:
@Configuration
public class QueueConfig {
/**
* 自动注入为SimpleRabbitListenerContainerFactory的消息序列化转换器
*/
@Bean
public MessageConverter messageConverter() {
return new Jackson2JsonMessageConverter();
}
/**
* 持久化交换机
*/
@Bean(name = "exchange")
public FanoutExchange exchange() {
return new FanoutExchange("exchange1", true, false);
}
/**
* 持久化队列
*/
@Bean
public Queue queue() {
return new Queue("queue", true);
}
/**
* 将队列和exchange绑定
*
* @return binding
*/
@Bean
Binding bindingSmsExchangeSmsQueue() {
return BindingBuilder.bind(queue()).to(exchange());
}
}
特殊延时队列的配置
延时队列的用法这里就不详细说了,参考Spring Boot与RabbitMQ结合实现延迟队列的示例,有些场景如未支付订单30分钟过期等,可通过延时队列实现
@Bean
public Queue delayQueue(){
return QueueBuilder.durable("delayQueue") //队列名称
.withArgument("x-message-ttl",10000) //死信时间
.withArgument("x-dead-letter-exchange", "") //死信重新投递的交换机
.withArgument("x-dead-letter-routing-key", "queue")//路由到队列的routingKey
.build();
}
启动应用测试一下
启动应用,在rabbit管理web查看所有队列
- 所有队列
- 查看delayQueue详情,框框中为延时配置
将"x-message-ttl"参数改成20000重启发现问题,控制队列里面的参数也没有修改成功
修改带参数队列失败的问题
问题分析
根据日志提示,队列已经存在而且参数不一致导致,然后查看源码在RabbitAdmin发现下面代码,在创建队列失败的时候会调用logOrRethrowDeclarationException方法,logOrRethrowDeclarationException方法中发布了一个DeclarationExceptionEvent事件,到这里解决思路有,监听这个事件,然后删除相应的队列 想学习更多java知识的朋友可以进群:874811168 一起学习 还有全套的免费资料领取
private DeclareOk[] declareQueues(final Channel channel, final Queue... queues) throws IOException {
List<DeclareOk> declareOks = new ArrayList<DeclareOk>(queues.length);
for (int i = 0; i < queues.length; i++) {
Queue queue = queues[i];
if (!queue.getName().startsWith("amq.")) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("declaring Queue '" + queue.getName() + "'");
}
try {
try {
DeclareOk declareOk = channel.queueDeclare(queue.getName(), queue.isDurable(),
queue.isExclusive(), queue.isAutoDelete(), queue.getArguments());
declareOks.add(declareOk);
}
catch (IllegalArgumentException e) {
if (this.logger.isDebugEnabled()) {
this.logger.error("Exception while declaring queue: '" + queue.getName() + "'");
}
try {
if (channel instanceof ChannelProxy) {
((ChannelProxy) channel).getTargetChannel().close();
}
}
catch (TimeoutException e1) {
}
throw new IOException(e);
}
}
catch (IOException e) {
logOrRethrowDeclarationException(queue, "queue", e);
}
}
else if (this.logger.isDebugEnabled()) {
this.logger.debug(queue.getName() + ": Queue with name that starts with 'amq.' cannot be declared.");
} 想学习更多java知识的朋友可以进群:874811168 一起学习 还有全套的免费资料领取
}
return declareOks.toArray(new DeclareOk[declareOks.size()]);
}
private <T extends Throwable> void logOrRethrowDeclarationException(Declarable element, String elementType, T t)
throws T {
DeclarationExceptionEvent event = new DeclarationExceptionEvent(this, element, t);
this.lastDeclarationExceptionEvent = event;
if (this.applicationEventPublisher != null) {
this.applicationEventPublisher.publishEvent(event);
}
if (this.ignoreDeclarationExceptions || (element != null && element.isIgnoreDeclarationExceptions())) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Failed to declare " + elementType
+ ": " + (element == null ? "broker-generated" : element)
+ ", continuing...", t);
}
else if (this.logger.isWarnEnabled()) {
Throwable cause = t;
if (t instanceof IOException && t.getCause() != null) {
cause = t.getCause();
}
this.logger.warn("Failed to declare " + elementType
+ ": " + (element == null ? "broker-generated" : element)
+ ", continuing... " + cause);
}
}
else {
throw t;
}
}
解决方法
写一个DeclarationExceptionEvent事件监听,处理创建失败的队列,既删除掉
@Component
public class DeclarationExceptionEventListener {
想学习更多java知识的朋友可以进群:874811168 一起学习 还有全套的免费资料领取
@Autowired
private AmqpAdmin rabbitAdmin;
@EventListener(classes = DeclarationExceptionEvent.class)
public void listen(DeclarationExceptionEvent event) {
final Declarable declarable = event.getDeclarable();
if (declarable instanceof Queue) {
final Queue queue = (Queue) declarable;
rabbitAdmin.deleteQueue(queue.getName());
}
}
}
改完重启应用,只有一条异常日志(原来4条),还有一条的原因是第一次创建失败发布事件,我们监听了事件进行处理。查看rabbit控制台,参数修改成功。
RabbitMQ进阶使用-延时队列的配置(Spring Boot)的更多相关文章
- RabbitMQ学习之延时队列
原帖参考:http://www.cnblogs.com/telwanggs/p/7124687.html?utm_source=itdadao&utm_medium=referral http ...
- (转) RabbitMQ学习之延时队列
http://blog.csdn.net/zhu_tianwei/article/details/53563311 在实际的业务中我们会遇见生产者产生的消息,不立即消费,而是延时一段时间在消费.Rab ...
- C#通过rabbitmq实现定时任务(延时队列)
本文主要讲解如何通过RabbitMQ实现定时任务(延时队列) 环境准备 需要在MQ中进行安装插件 地址链接 插件介绍地址:https://www.rabbitmq.com/blog/2015/04/1 ...
- RabbitMQ:伪延时队列
目录 一.什么是延时队列 二.RabbitMQ实现 三. 延时队列的问题 四.解决RabbitMQ的伪延时方案 ps:伪延时队列先卖个关子,我们先了解下延时队列. 一.什么是延时队列 所谓延时队列是指 ...
- 在IDEA中配置spring boot项目的热更新
在我使用IDEA的过程中,我发现Spring Boot项目本来自带的一个热部署工具无法使用,这里在参考各家博客后给出解决方案: 修改POM 首先POM文件需要包含spring boot的热部署工具,m ...
- Linux系统CentOS 7配置Spring Boot运行环境
从阿里云新买的一台Linux服务器,用来部署SpringBoot应用,由于之前一直使用Debian版本,环境配置有所不同,也较为繁琐,本文主要介绍CentOS下配置SpringBoot环境的过程 新建 ...
- vs code 配置spring boot开发环境
一.环境变量 jdk环境变量一键设置 管理員运行 - 一支小白 - 博客园https://www.cnblogs.com/startnow/p/7416533.html 二.安装插件 1.Java E ...
- 如何配置Spring Boot Tomcat
1.概述 Spring Boot Web应用程序默认包含预配置的嵌入式Web服务器.但在某些情况下,我们要修改默认配置以满足自定义要求. 在本教程中,我们将介绍通过application.proper ...
- spring boot:基于profile的多环境配置(spring boot 2.3.4)
一,为什么要进行多环境配置? 1,没有人会在生产环境中进行开发和测试, 所以通常会有多个环境的划分: 工程师本地的开发环境 进行测试的测试环境 最终上线的生产环境 每个环境对应不同的数据库/缓存等数据 ...
随机推荐
- 常见字符集&乱码问题
字符集 常用字符集分类 ASCII及其扩展字符集 作用:表语英语及西欧语言. 位数:ASCII是用7位表示的,能表示128个字符:其扩展使用8位表示,表示256个字符. 范围:ASCII从00到7F, ...
- asp.net 虹软人脸识别sdk 释放内存
初始化时申请内存,用完记得释放,不然就会报“内存已满”的. 使用时: pMem = Marshal.AllocHGlobal(detectSize); 释放内存: Marshal.FreeHGloba ...
- 虚拟机ubuntu的常用命令集合
一.文件/文件管理 ls 列出当前目录文件(不包括隐含文件) ls -a 列出当前目录文件(包括隐含文件) ls -l 列出当前目录下文件的详细信息 cd .. 回当前目录的上一级目录 cd -回上一 ...
- nodejs实现文件的拷贝复制
var fs = require( 'fs' ), stat = fs.stat; /* 05 * 复制目录中的所有文件包括子目录 06 * @param{ String } 需要复制的目录 07 * ...
- Linq to XML 增删改查
Linq to XML同样是对原C#访问XML文件的方法的封装,简化了用xpath进行xml的查询以及增加,修改,删除xml元素的操作.C#访问XML文件的常用类:XmlDocument,XmlEle ...
- pandas更换index,column名称
1)仅换掉index名称 df.index = list 2)调整index时,后面的项目也要跟着调整: df.reindex(list) 注意如果list中出现了df中没有的index,后面的项目会 ...
- lanmp环境中创建个软连接
进入default,创建关于框架的链接 然后编辑配置文件 这样就可以在线上访问了.
- python记录_day30 多进程
1.什么是进程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础. 同一个程序执行两次,就会产生两个进程 ## 进程调度算 ...
- Windows自动登录设置 Windows免密登录
设置方法如下:开始-运行-control userpasswords2:打开用户账号管理页面,将“要使用本机,用户必须输入用户名和密码”前面的勾去掉:点击 应用,确定之后.会提示用户输入需要自动登陆系 ...
- element中使用button会刷新一遍页面
会刷新: <el-form-item> <button @click="register('form')" class="submitBtn&qu ...