Springboot + RabbitMq 消息队列

news/2024/4/29 2:50:29/文章来源:https://blog.csdn.net/zhangbinlong/article/details/128948422

前言

一、RabbitMq简介

1、RabbitMq场景应用,RabbitMq特点

场景应用
以订单系统为例,用户下单之后的业务逻辑可能包括:生成订单、扣减库存、使用优惠券、增加积分、通知商家用户下单、发短信通知等等。在业务发展初期这些逻辑可能放在一起同步执行,随着业务的发展订单量增长,需要提升系统服务的性能,这时可以将一些不需要立即生效的操作拆分出来异步执行。这种场景下就可以用 MQ ,在下单的主流程(比如扣减库存、生成订单)完成之后发送一条消息到 MQ 让主流程快速完结,而由另外的单独消费线程拉取MQ的消息(或者由 MQ 推送消息。
特点
RabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现。

  • AMQP :Advanced Message
    Queue,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。

  • 可靠性(Reliability) RabbitMQ 使用一些机制来保证可靠性,如持久化、传输确认、发布确认。

  • 灵活的路由(Flexible Routing) 在消息进入队列之前,通过 Exchange
    来路由消息的。对于典型的路由功能,RabbitMQ 已经提供了一些内置的 Exchange 来实现。针对更复杂的路由功能,可以将多个
    Exchange 绑定在一起,也通过插件机制实现自己的 Exchange 。

  • 消息集群(Clustering)
    多个 RabbitMQ 服务器可以组成一个集群,形成一个逻辑 Broker 。

  • 高可用(Highly Available Queues)
    队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用。

  • 多种协议(Multi-protocol)
    RabbitMQ 支持多种消息队列协议,比如 STOMP、MQTT 等多种消息中间件协议。

  • 多语言客户端(Many Clients)
    RabbitMQ 几乎支持所有常用语言,比如Java、Python 、Ruby 、PHP 、C# 、JavaScript 等。

  • 管理界面(Management UI)
    RabbitMQ 提供了一个易用的用户界面,使得用户可以监控和管理消息 Broker 的许多方面。

  • 跟踪机制(Tracing)
    如果消息异常,RabbitMQ 提供了消息跟踪机制,使用者可以找出发生了什么。

  • 插件机制(Plugin System)
    RabbitMQ 提供了许多插件,来从多方面进行扩展,也可以编写自己的插件。

2、RabbitMq工作流程

  • publisher连接到rabbitMQ Broker,创建connection,开启channel。声明交换机类型、名称、是否持久化等。

  • 消息可靠投递(开启confirmCallback returnCallback),并指定消息是否持久化等属性和routing key。

  • exchange收到消息之后,根据routing key路由到跟当前交换机绑定的相匹配的(存)队列里面。

  • consumer监听接收到消息之后开始业务处理,然后发送一个ack确认告知消息已经被消费。
    rabbitMQ Broker收到ack之后将对应的消息从队列里面删除掉。
    如下图:
    在这里插入图片描述

  • Message
    消息,消息是不具名的,它由消息头和消息体组成。消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括routing-key(路由键)、priority(相对于其他消息的优先权)、delivery-mode(指出该消息可能需要持久性存储)等。

  • Publisher
    消息的生产者,也是一个向交换器发布消息的客户端应用程序。

  • Exchange
    交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列。

  • Binding
    绑定,用于消息队列和交换器之间的关联。一个绑定就是基于路由键将交换器和消息队列连接起来的路由规则,所以可以将交换器理解成一个由绑定构成的路由表。

  • Queue
    消息队列,用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走。

  • Connection
    网络连接,比如一个TCP连接。

  • Channel
    信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内地虚拟连接,AMQP 命令都是通过信道发出去的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说建立和销毁 TCP 都是非常昂贵的开销,所以引入了信道的概念,以复用一条 TCP 连接。

  • Consumer
    消息的消费者,表示一个从消息队列中取得消息的客户端应用程序。

  • Virtual Host
    虚拟主机,表示一批交换器、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个 vhost 本质上就是一个 mini 版的 RabbitMQ 服务器,拥有自己的队列、交换器、绑定和权限机制。vhost 是 AMQP 概念的基础,必须在连接时指定,RabbitMQ 默认的 vhost 是 / 。

  • Broker
    表示消息队列服务器实体。

二 引用RabbitMq

将RabbitMq配置成插件使用
1.创建工程 pom.xml 引用jar
在这里插入图片描述

		<!--mq 模块--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bus-amqp</artifactId></dependency><!--提供服务发现能力--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-commons</artifactId></dependency>
  1. 创建RabbitMQConfig

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.CustomExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.HashMap;
import java.util.Map;
@Configuration
public class RabbitMQConfig {public static final String DELAYED_SWITCH_OFF_QUEUE_NAME = "delay.queue.switchOff.delay.queue";public static final String DELAYED_SWITCH_OFF_EXCHANGE_NAME = "delay.queue.switchOff.delay.exchange";public static final String DELAYED_SWITCH_OFF_ROUTING_KEY = "delay.queue.switchOff.delay.routingkey";/*** @desciption 控制设备开关延时关闭* @author zhangbl* @Date : 2022-08-08 16:29**/@Beanpublic Queue immediateSwitchOffQueue() {return new Queue(DELAYED_SWITCH_OFF_QUEUE_NAME,true);}@Beanpublic CustomExchange customSwitchOffExchange() {Map<String, Object> args = new HashMap<>();args.put("x-delayed-type", "direct");return new CustomExchange(DELAYED_SWITCH_OFF_EXCHANGE_NAME, "x-delayed-message", true, false, args);}@Beanpublic Binding bindingSwitchOffNotify() {return BindingBuilder.bind(immediateSwitchOffQueue()).to(customSwitchOffExchange()).with(DELAYED_SWITCH_OFF_ROUTING_KEY).noargs();}
}
  1. 创建RabbitMq注解类 EnableRabbitMq
import com.common.rabbitmq.config.RabbitMQConfig;
import org.springframework.context.annotation.Import;import java.lang.annotation.*;/*** <p>* 开启支持RabbitMQ*/
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({ RabbitMQConfig.class })
public @interface EnableRabbitMq {}
  1. 服务引用Mq pom.xml添加mq插件jar包
<dependency><groupId>com.mq</groupId><artifactId>common-rabbitmq</artifactId>
</dependency>
  1. 启动类引用 @EnableRabbitMq 注解
@EnableRabbitMq
@SpringBootApplication
public class TestApplication{public static void main(String[] args) {SpringApplication.run(TestApplication.class, args);}
}
  1. 创建消费者实现类
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;@Slf4j
@Component
public class SwitchOffListener {@Resourceprivate RedisTemplate strRedisTemplate;@Resourceprivate RabbitTemplate rabbitTemplate;@RabbitListener(queues = RabbitMQConfig.DELAYED_SWITCH_OFF_QUEUE_NAME)public void onExpired(Message message, Channel channel) throws IOException {String msg = new String(message.getBody());//获取锁,设置有效期,防止程序异常没有释放锁导致死锁String str = UUID.randomUUID().toString();String lockKey = RabbitMQConfig.DELAYED_SWITCH_OFF_QUEUE_NAME + msg;Boolean lock = strRedisTemplate.opsForValue().setIfAbsent(lockKey, str, Duration.ofSeconds(5));try {if(lock){log.info("========进入开关延时关闭处理==========");//具体实现}log.info("开关延时关闭成功!!!");} catch (Exception e) {e.printStackTrace();} finally {//释放锁if (str.equals(strRedisTemplate.opsForValue().get(lockKey))){strRedisTemplate.delete(lockKey);}}channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);}
  1. 业务调用
 @Autowiredprivate RabbitTemplate rabbitTemplate;public void machDeviceCloseTime(String msg) {if(StringUtils.isNotBlank(msg){try {rabbitTemplate.convertAndSend(RabbitMQConfig.DELAYED_SWITCH_OFF_EXCHANGE_NAME,RabbitMQConfig.DELAYED_SWITCH_OFF_ROUTING_KEY, message, listener ->{listener.getMessageProperties().setDelay(1000);//1毫秒后发送mq消息return listener;});}} catch (JsonProcessingException e) {throw new RuntimeException(e);}}}
  1. application.yml 添加配置
spring:rabbitmq:# mq单机模式配置host: 127.0.0.1port: 5672# mq集群模式配置方式addresses: 127.0.0.1:5672,127.0.0.2:5672,127.0.0.3:5672username: adminpassword: 123456virtual-host: /test#这个配置是保证提供者确保消息推送到交换机中,不管成不成功,都会回调publisher-confirm-type: correlated#保证交换机能把消息推送到队列中publisher-returns: true#这个配置是保证消费者会消费消息,手动确认listener:simple:acknowledge-mode: manualtemplate:mandatory: true

配置Rabbitmq 集群参照 https://blog.csdn.net/zhangbinlong/article/details/127067044?spm=1001.2014.3001.5502

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_255483.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

openGL学习之GLFW和GLAD的下载和编译

背景:为什么使用GLFW和GLADOPenGL环境 目前主流的桌面平台是GLFW和GLAD之前使用的GLUT和Free GLUT已经基本淘汰了&#xff0c;所以记录一下如何下载GLFW和GLAD并且编译.GLFW下载:An OpenGL library | GLFW复制到你想存放的位置,我这里就存放到C盘Libaray文件夹下了,这里是我存放…

中国区注册使用ChatGPT指南(OpenAI‘s services are not available in your country)

ChatGPT又火了&#xff0c;各大平台热搜提到手软。暴增的访问量&#xff0c;即使强如ChatGPT&#xff0c;也表示顶不住了。Openai表示服务器已满负荷&#xff0c;ChatGPT暂无法提供服务由于目前ChatGPT未在中国开放&#xff0c;所以国内目前是无法注册使用ChatGPT。但我经过一番…

『 MySQL篇 』:MySQL表的聚合与联合查询

基础篇 MySQL系列专栏(持续更新中 …)1『 MySQL篇 』&#xff1a;库操作、数据类型2『 MySQL篇 』&#xff1a;MySQL表的CURD操作3『 MySQL篇 』&#xff1a;MySQL表的相关约束4『 MySQL篇 』&#xff1a;MySQL表的聚合与联合查询目录一. 聚合查询1.1 聚合函数1.2 GROUP BY子句…

Python将字典转换为csv

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。喜欢通过博客创作的方式对所学的知识进行总结与归纳,不仅形成深入且独到的理…

MySQL篇02-三大范式,多表查询

数据入库时,由于数据设计不合理&#xff0c;会存在数据重复、更新插入异常等情况, 故数据库中表的设计遵循的设计规范&#xff1a;三大范式1.第一范式(1NF)要求数据库的每一列都是不可分割的原子数据项&#xff0c;即原子性。强调的是列的原子性&#xff0c;即数据库中每一列的…

攀升MaxBook P2电脑U盘重装系统方法教学

攀升MaxBook P2电脑U盘重装系统方法教学。攀升MaxBook P2电脑是一款性价比非常高的笔记本。有用户购买了这款电脑后&#xff0c;想要将系统进行重装。今天和大家分享一个U盘重装系统的方法&#xff0c;学会这个方法后以后就可以自己轻松去重装电脑系统了。接下来一起看看具体的…

相机坐标系的正向投影和反向投影

1 、正向投影: 世界坐标系到像素坐标系 世界3D坐标系(x, y, z) 到图像像素坐标(u,v)的映射过程 &#xff08;1&#xff09;世界坐标系到相机坐标系的映射。 两个坐标系的转换比较简单&#xff0c;就是旋转矩阵 平移矩阵&#xff0c;旋转矩阵则是绕X&#xff0c; Y&#xff…

Thread 类及常见方法

Thread 类是 JVM 用来管理线程的一个类&#xff0c;换句话说&#xff0c;每个线程都有一个唯一的 Thread 对象与之关联。用我们上面的例子来看&#xff0c;每个执行流&#xff0c;也需要有一个对象来描述&#xff0c;类似下图所示&#xff0c;而 Thread 类的对象就是用来描述一…

分享111个JS焦点图代码,总有一款适合您

分享111个JS焦点图代码&#xff0c;总有一款适合您 111个JS焦点图代码下载链接&#xff1a;https://pan.baidu.com/s/1GxjW5m9DNOPEQd-Qf_gGSA?pwd4aci 提取码&#xff1a;4aci Python采集代码下载链接&#xff1a;https://wwgn.lanzoul.com/iKGwb0kye3wj jQuery宽屏左右…

没有人能比我快,用Python写一个自动填写答案的脚本

前言 不是标题党&#xff0c;真的就是没有人比我快&#xff0c;今天用Python写了个自动填写答案的脚本&#xff0c;快就算了&#xff0c;准确率还是百分之百 话不多说 咱先看代码 后看效果 不想看全文的 点击文末名片 领取源码 环境使用 Python 3.8Pycharm 模块使用 imp…

Request Method: OPTIONS

节选自https://blog.csdn.net/Amnesiac666/article/details/121105088版权归原作者所有&#xff0c;如有侵权请联系删除Request Method: OPTIONS一些接口在请求时&#xff0c;会自动发送一个的请求&#xff0c;我查了一遍代码&#xff0c;不是代码中写明的。 网上给出的解释涉及…

Pinecone:一款专为红队研究人员设计的WLAN网络安全审计框架

关于Pinecone Pinecone是一款专为红队研究人员设计的WLAN网络安全审计框架&#xff0c;该工具基于模块化开发&#xff0c;允许广大研究人员根据任务需求进行自定义功能扩展。Pinecone设计之初专用于树莓派&#xff0c;可以将树莓派打造为便携式无线网络安全审计工具&#xff0…

java面试题(十六)springBoot

1.1 说说你对Spring Boot的理解 参考答案 从本质上来说&#xff0c;Spring Boot就是Spring&#xff0c;它做了那些没有它你自己也会去做的Spring Bean配置。Spring Boot使用“习惯优于配置”的理念让你的项目快速地运行起来&#xff0c;使用Spring Boot很容易创建一个能独立运…

广告深度学习计算:向量召回索引的演进以及工程实现

问题定义召回操作通常作为搜索/推荐/广告的第一个阶段&#xff0c;主要目的是从巨大的候选集中选出相对合适的条目&#xff0c;交由后链路的排序等流程进行进一步的择优。因此&#xff0c;召回问题本质上就是一个大规模的最值的搜索问题&#xff1a;对于评分 和候选集 &#x…

最短路之Dijkstra(15张图解)

&#x1f33c;多年后再见你 - 乔洋/周林枫 - 单曲 - 网易云音乐 闲来无事听听歌 Dijkstra可解决“单源最短路径”问题 四种最短路算法 Floyd算法 时间复杂度高&#xff0c;但实现容易&#xff08;5行核心代码&#xff09;&#xff0c;可解决负权边&#xff0c;适用于数据范围…

方法的定义与使用详解

我们常用创建一个class修饰的就是一个类 其中有一个main方法&#xff0c;是主要的启动方法 这里写目录标题我们正常修饰的方法是由返回值的&#xff0c;但是用void修饰的没有static的使用方法中形参和实参的使用值传递引用传递类跟对象的关系this构造器--构造方法这个&#xf…

uniapp+java/springboot实现微信小程序APIV3支付功能

微信小程序的支付跟H5的支付和APP支付流程不一样&#xff0c;本次只描述下小程序支付流程。 一.账号准备 1.微信小程序账号 文档&#xff1a;小程序申请 小程序支付需要先认证&#xff0c;如果你有已认证的公众号&#xff0c;也可以通过公众号免费注册认证小程序。 一般30…

自定义input[type=file]上传按钮样式的四种方案,你知道几种?

目录前言方案1 opacity: 0;实现方案2 display:none样式元素选择 &#xff1a;label样式元素选择&#xff1a;其他元素::file-selector-button兼容性用法&#x1f9e8;&#x1f9e8;&#x1f9e8; 大家好&#xff0c;我是搞前端的半夏 &#x1f9d1;&#xff0c;一个热爱写文的前…

二、Linux文件 - Open函数讲解实战

目录 1.Open函数讲解 2.open函数实战 2.1 man 1 ls 查询Shell命令 2.2 man 2 open 查看系统调用函数 2.3项目实战 1.Open函数讲解 高频使用的Linux系统调用&#xff1a;open write read close Linux自带的工具&#xff1a;man手册&#xff1a; man 1是普通的shell…

【树和二叉树】数据结构二叉树和树的概念认识

前言&#xff1a;在之前&#xff0c;我们已经把栈和队列的相关概念以及实现的方法进行了学习&#xff0c;今天我们将认识一个新的知识“树”&#xff01;&#xff01;&#xff01; 目录1.树概念及结构1.1树的概念1.2树的结构1.3树的相关概念1.4 树的表示1.5 树在实际中的运用&a…