rabbitmq结合spring实现消息队列优先级的方法

发布时间 - 2026-01-10 23:06:14    点击率:

 1.1项目背景:做一个灾情预警的消息平台,灾情检查系统需要向消息平台里面推送消息,这里是典型的异构系统的消息传递,我们需要选择一个中间件作为消息队列,调研分析了rabbitmq,zeromq,activemq,kafka等消息中间件,综合性能,安全,可持久化等角度果断选择了rabbitmq作为我们的消息中间件 (其实这里是因为rabbitmq 是spring官方支持的,开发起来方便)。需求上我们有多种类型的消息,这里有紧急推送的和一般的等区分,高并发时,就会有对消息进行优先推送的情况出现,于是rabbitmq消息队优先级的推送功能是我们需要解决的首个技术点.

1.2技术调研:这里一个概念需要说明,为什么说是消息队列的优先级而不是消息的优先级,来看下消息队列的工作原理

生产者生成消息打到交换机里面(如果没有声明交换机,会打到default exchange里面),交换机绑定一个或多个队列,消息进入队列里面,消费者一直在监听队列,发现队列里面有消息就开始消费,这里就是一个消息传递的过程,queue是一个栈队列,栈是先进先出的,就是说消息来了依次排队,一个队列并不能实现消息的插队和优先推送的功能。但是如果说我们的多个队列有不同的优先级,不同优先级的消息通过roatingkey进入不同的队列,优先级高的队列消息被优先消费,这样也能形成一个相对意义上的优先级,所以说这里不是消息的优先级而是队列的优先级.

1.2.1 为什么说是相对意义上的优先级

有并发才有优先级,如果每个消息都能被瞬间处理也不会有消息优先推送的需求,那我们看看消息会在哪里阻塞

1,queue,很明显高并发的时候队列里面是会存在很多消息的,2,eschange ,高并发的时候producer发送给exchange的时候也会产生阻塞。

第一种情况由于我们队列已经定义优先级了,所以进入队列的消息都是同种优先级别的,并不需要插队。而对于第二种情况,消息在exchange时阻塞时并不能实现消息优先进入队列,依然是一个依次处理的情景,但是由于exchang到queue的处理速度极快,所有我们忽略了这块的优先级。

1.2.3 代码实现

在rabbitmq3.5版本之前,官方并没有实现队列优先级的功能,但论坛里面有一些插件可以实现(末尾附链接),这里我们主要说3.5版本之后的实现

1.2.3.1 Java代码

Connectionconn =RabbitMQConnectionUtil.getRabbitmqConnection();//创建连接 
    Channelchannel = conn.createChannel();//创建channel 
    Map<String,Object> arg = newHashMap<String, Object>();  
    arg.put("x-max-priority",10); //队列的属性参数 有10个优先级别 
    // 声明(创建)队列 
    //channel.queueDeclare(QUEUE_NAME, false, false, false, null); 
    channel.queueDeclare(QUEUE_NAME,true,false, false, arg); 
    // 消息内容 
    String message ="Hello World!"; 
    channel.basicPublish("",QUEUE_NAME, null, message.getBytes()); 
    BasicPropertiesprop =new BasicProperties(null, null, null, null, 1, 
    null, null, null, null, null, null, null, null,null);//消息的参数,声明该消息的优先级是1 
    channel.basicPublish("",QUEUE_NAME, prop, message.getBytes()); //消息发布 
    System.out.println("[x] Sent '" + message + "'"); 
    //关闭通道和连接 
    channel.close(); 
    conn.close(); 

客户端看下结果:

1.2.3.2结合spring实现: 

1.2.3.2.1 xml配置: 

<beans xmlns="http://www.springframework.org/schema/beans" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:rabbit="http://www.springframework.org/schema/rabbit"  
  xsi:schemaLocation="http://www.springframework.org/schema/beans  
  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  http://www.springframework.org/schema/rabbit 
  http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd" > 
  <description>rabbitmq 连接服务配置</description> 
  <!-- 连接配置 --> 
  <rabbit:connection-factory id="connectionFactory" host="${rabbit.ip}" username="${rabbit.username}"  
  password="${rabbit.password}" port="${rabbit.port}" virtual-host="${rabbit.vhost}"/> 
  <rabbit:admin connection-factory="connectionFactory"/> 
  <rabbit:template id="amqpTemplate" connection-factory="connectionFactory" /> 
  <!-- spring template声明--> 
  <!-- 声明一个队列 --> 
  <rabbit:queue id="test_queue_key" name="test_queue_key" durable="true" auto-delete="false" exclusive="false"> 
   <rabbit:queue-arguments> 
    <entry key="x-max-priority"> 
      <value type="java.lang.Integer">10</value>//这个地方一定是integer的,别的不好使!! 
    </entry> 
   </rabbit:queue-arguments> 
  </rabbit:queue> 
  <!-- 监听配置queues:监听的队列,多个的话用逗号(,)分隔 ref:监听器--> 
  <rabbit:listener-container connection-factory="connectionFactory" acknowledge="auto"> 
    <rabbit:listener queue-names="test_queue_key" ref="queueListenter" method="onMessage"/> 
  </rabbit:listener-container> 
<bean id="queueListenter" class="com.DF.spring.springAMQP.QueueListener" /> 

1.2.3.2.2代码部分:

producter:

AbstractApplicationContext ctx = new  
ClassPathXmlApplicationContext("classpath:/spring/rabbitmq-contextDemo2.xml"); 
RabbitTemplate amqpTemplate = ctx.getBean(RabbitTemplate.class); 
 Random random = new Random(); 
  for (int i=0; i< 1000; i++){ 
    final int priority = random.nextInt(10 - 1 + 1) + 1;//随机的优先级 
    amqpTemplate.convertAndSend("test_queue_key", (Object)("hello world"), new MessagePostProcessor() { 
     @Override 
     public Message postProcessMessage(Message message) throws AmqpException { 
      message.getMessageProperties().setPriority(priority); 
      return message; 
     } 
    }); 
  } 

customer: 

public class QueueListener implements MessageListener{ 
 @Override 
 public void onMessage(Message message) { 
  try{ 
   System.out.print("[x] 接收到的消息:"+new String(message.getBody(),"utf-8")+"&&&"+"优先级"+message.getMessageProperties().getPrority()); 
   Thread.sleep(1000); 
  }catch(Exception e){ 
   e.printStackTrace(); 
  } 
 } 
} 

从客户端看下队列里面的消息:

我们发送随机优先级的消息进入队列,看看消费端打印出来的消息:

到这里,rabbitmq结合spring的demo功能实现......

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# java  # spring  # 消息队列  # 消息队列优先级  # SpringBoot使用RabbitMQ延时队列(小白必备)  # SpringBoot集成RabbitMQ的方法(死信队列)  # springboot实现rabbitmq的队列初始化和绑定  # Spring Boot与RabbitMQ结合实现延迟队列的示例  # 消息队列 RabbitMQ 与 Spring 整合使用的实例代码  # Spring学习笔记3之消息队列(rabbitmq)发送邮件功能  # Spring项目集成RabbitMQ及自动创建队列  # 多个  # 是一个  # 打到  # 并不能  # 都是  # 客户端  # 也不  # 来了  # 会有  # 是因为  # 也会  # 都能  # 也能  # 会在  # 意义上  # 才有  # 如果没有  # 做一个  # 如果说  # 可以实现 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 装修招标网站设计制作流程,装修招标流程?  详解Android图表 MPAndroidChart折线图  如何在阿里云ECS服务器部署织梦CMS网站?  Laravel如何为API编写文档_Laravel API文档生成与维护方法  如何挑选最适合建站的高性能VPS主机?  利用 Google AI 进行 YouTube 视频 SEO 描述优化  网站制作价目表怎么做,珍爱网婚介费用多少?  Laravel如何处理CORS跨域问题_Laravel项目CORS配置与解决方案  Laravel Asset编译怎么配置_Laravel Vite前端构建工具使用  如何快速搭建安全的FTP站点?  如何快速打造个性化非模板自助建站?  html5audio标签播放结束怎么触发事件_onended回调方法【教程】  QQ浏览器网页版登录入口 个人中心在线进入  美食网站链接制作教程视频,哪个教做美食的网站比较专业点?  常州企业网站制作公司,全国继续教育网怎么登录?  香港网站服务器数量如何影响SEO优化效果?  Laravel如何使用Spatie Media Library_Laravel图片上传管理与缩略图生成【步骤】  如何用ChatGPT准备面试 模拟面试问答与职场话术练习教程  Gemini手机端怎么发图片_Gemini手机端发图方法【步骤】  Python文本处理实践_日志清洗解析【指导】  Laravel怎么使用artisan命令缓存配置和视图  如何在服务器上三步完成建站并提升流量?  北京企业网站设计制作公司,北京铁路集团官方网站?  Laravel如何处理JSON字段_Eloquent原生JSON字段类型操作教程  音响网站制作视频教程,隆霸音响官方网站?  Laravel中的Facade(门面)到底是什么原理  Laravel怎么解决跨域问题_Laravel配置CORS跨域访问  HTML5空格在Angular项目里怎么处理_Angular中空格的渲染问题【详解】  EditPlus中的正则表达式实战(6)  nodejs redis 发布订阅机制封装实现方法及实例代码  网站制作壁纸教程视频,电脑壁纸网站?  Laravel怎么防止CSRF攻击_Laravel CSRF保护中间件原理与实践  如何用y主机助手快速搭建网站?  如何在阿里云虚拟主机上快速搭建个人网站?  laravel怎么配置Redis作为缓存驱动_laravel Redis缓存配置教程  HTML透明颜色代码怎么让图片透明_给img元素加透明色的技巧【方法】  HTML 中动态设置元素 name 属性的正确语法详解  东莞市网站制作公司有哪些,东莞找工作用什么网站好?  高端建站三要素:定制模板、企业官网与响应式设计优化  Laravel Seeder怎么填充数据_Laravel数据库填充器的使用方法与技巧  JavaScript中如何操作剪贴板_ClipboardAPI怎么用  Laravel如何实现URL美化Slug功能_Laravel使用eloquent-sluggable生成别名【方法】  Laravel辅助函数有哪些_Laravel Helpers常用助手函数大全  php打包exe后无法访问网络共享_共享权限设置方法【教程】  Python进程池调度策略_任务分发说明【指导】  php485函数参数是什么意思_php485各参数详细说明【介绍】  如何在IIS中配置站点IP、端口及主机头?  百度输入法ai组件怎么删除 百度输入法ai组件移除工具  南京网站制作费用,南京远驱官方网站?  Laravel如何发送系统通知?(Notification渠道示例)