🥳🥳Welcome 的Huihui's Code World ! !🥳🥳
接下来看看由辉辉所写的关于Docker的相关操作吧
目录
[🥳🥳Welcome 的Huihui's Code World ! !🥳🥳](#🥳🥳Welcome 的Huihui's Code World ! !🥳🥳)
[一. RabbitMQ是什么](#一. RabbitMQ是什么)
[二. Docker安装部署RabbitMQ](#二. Docker安装部署RabbitMQ)
前言
其实在讲解RabbitMQ之前,我们应该先明白为什么要使用RabbitMQ,RabbitMQ能给我们带来什么效益...
在公司中做项目时,当项目已经迭代了几个版本了,代码量已经很大了,此时我们需要再增加一个业务功能那么这就需要提供新增一个业务接口,但如果这个时候再去更改原来的代码就会很困难,需要修改很多的地方。。。
其实这个时候我们就可以使用到消息队列去优化项目,这样就算我们后来有新的功能需要添加,也不用跟上面一样修改很多的代码。
1.什么是MQ
Message queue相当于一个中间件,用于生产方通过MQ与消费方之间的交互作用
服务之间最常见的通信方式是直接调用彼此来通信,消息从一端发出后立即就可以达到另一端,称为即时消息通讯(同步通信)
也就是两人面对面交流,必须同步进行,除此之外不做任何事情,就像打电话一样的
消息从某一端发出后,首先进入一个容器进行临时存储,当达到某种条件后,再由这个容器发送给另一端,称为延迟消息通讯(异步通信)
相当于通过第三方转述对话,可能有消息的延迟,但不需要二人时刻保持联系,消息传给第三方后,两人可以做其他自己想做的事情,当需要获取对方说话的内容时,直接从消息队列里获取即可。就像发微信一样
2.理解MQ
- 消息:就是两台计算机间传送的数据单位;本质上就是一段数据,它能被一个或者多个应用程序所理解,是应用程序之间传递的信息载体。消息可以非常简单,例如只包含文本字符串;也可以更复杂地嵌入对象。
- 队列:是数据结构中概念。在队列中,数据先进先出,后进后出,犹如排队做核酸。
- 消息队列:MQ是把消息和队列结合起来,称之为消息队列(Message Queue)。把要传输的数据(消息)与队列进行绑定,用队列先进先出机制来实现消息传递。消息队列由 生产者 和 消费者 两部分构成;生产者主要负责产生消息并把消息放入队列中,再由消费者去处理。消费者可以到指定队列中获取消息,或者订阅相应的队列,最后由MQ服务端进行消息推送。
3.生活案例分析与理解
看书案例
小红希望小明多读书,常寻找好书给小明看,之前的方式 是这样:小红问小明什么时候有空,把书给小明送去,并亲眼监督小明读完书才走.久而久之,两人都觉得麻烦. 后来的方式改成了:小红对小明说「我放到书架上的书你都要看」,然后小红每次发现不错的书都放到书架上,小明则看到书架上有书就拿下来看.【书架就是一个消息队列,小红是生产者,小明是消费者.】
案例分析
改变方式之后带来的好处
- 小红想给小明书的时候,不必问小明什么时候有空,亲手把书交给他了,小红只把书放到书架上就行了.这样小红小明的时间都更自由.
- 小红相信小明的读书自觉和读书能力,不必亲眼观察小明的读书过程,小红只要做一个放书的动作,很节省时间.
- 当明天有另一个爱读书的小伙伴小强加入,小红仍旧只需要把书放到书架上,小明和小强从书架上取书即可
- 书架上的书放在那里,小明阅读速度快就早点看完,阅读速度慢就晚点看完,没关系,比起小红把书递给小明并监督小明读完的方式,小明的压力会小一些
消息队列特点
- 解耦:每个成员不必受其他成员影响,可以更独立自主,只通过一个简单的容器来联系.
- 提速:小红选只要做一个放书的动作,为自己节省了大量时间.
- 广播:小红只需要劳动一次,就可以让多个小伙伴有书可读,这大大地节省了她的时间,也让新的小伙伴的加入成本很低.
- 错峰与流控:小红给书的频率不稳定,如果今明两天连给了五本,之后隔三个月才又给一本,那小明只要在三个月内从书架上陆续取走五本书读完就行了,压力就不那么大了.
也可以用生活中做核酸的例子来理解一下
**4.**MQ的使用场景
上面也已经用生活案例说明的MQ的使用的好处(场景),这里再来罗列以及分析对比一下...
(1)解耦
传统模式
系统间耦合性太强,如图所示,系统A在代码中直接调用系统B和系统C的代码,如果将来D系统接入,系统A还需要修改代码,过于麻烦!
中间件模式
将消息写入消息队列,需要消息的系统自己从消息队列中订阅,从而系统A不需要做任何修改。
(2)削峰
传统模式
并发量大的时候,所有的请求直接怼到数据库,造成数据库连接异常
中间件模式
系统A慢慢的按照数据库能处理的并发量,从消息队列中慢慢拉取消息
(3)异步
传统模式
一些非必要的业务逻辑以同步的方式运行,太耗费时间
中间件模式
将消息写入消息队列,非必要的业务逻辑以异步的方式运行,加快响应速度
5.常见的MQ
消息队列有很多,这里我们使用的是RabbitMQ,也可以选择使用其他的MQ...
那么接下来我就来讲述一下RabbitMQ的相关点
一. RabbitMQ是什么
RabbitMQ是一种开源的消息队列软件,它实现了高级消息队列协议(AMQP)标准。它可以在分布式系统中作为消息传递的中间层来处理异步通信和解耦。通过将生产者和消费者解耦,RabbitMQ可以提高系统的可靠性、扩展性和可维护性。它还支持多种编程语言和平台,并且具有许多高级功能,例如消息确认、消息持久化、消息路由和负载均衡等。RabbitMQ在企业应用程序、大数据、云计算、物联网等领域都得到广泛应用
- Server(Broker):接收客户端连接,实现AMQP协议的消息队列和路由功能的进程.
- Virtual Host:虚拟主机的概念,类似权限控制组,一个Virtual Host里可以有多个Exchange和Queue.
- Exchange:交换机,接收生产者发送的消息,并根据Routing Key将消息路由到服务器中的队列Queue.
- ExchangeType:交换机类型决定了路由消息行为,RabbitMQ中有三种类型Exchange,分别是fanout、direct、topic.
- Message Queue:消息队列,用于存储还未被消费者消费的消息.
- Message:由Header和body组成,Header是由生产者添加的各种属性的集合,包括Message是否被持久化、优先级是多少、由哪个Message Queue接收等.body是真正需要发送的数据内容.
- BindingKey:绑定关键字,将一个特定的Exchange和一个特定的Queue绑定起来.
二. Docker安装部署RabbitMQ
1.拉取镜像
注意获取镜像的时候要获取management版本的,不要获取last版本的,management版本的才带有管理界面
docker pull rabbitmq:management
2.安装
javadocker run -d \ --name my-rabbitmq \ -p 5672:5672 -p 15672:15672 \ -v /home/rabbitmq:/var/lib/rabbitmq \ --hostname my-rabbitmq-host \ -e RABBITMQ_DEFAULT_VHOST=my_vhost \ -e RABBITMQ_DEFAULT_USER=admin \ -e RABBITMQ_DEFAULT_PASS=admin \ --restart=always \ rabbitmq:management
-d
:表示以后台(守护进程)模式运行容器。--name my-rabbitmq
:指定容器的名称为my-rabbitmq。-p 5672:5672 -p 15672:15672
:将主机的5672和15672端口映射到容器内对应的端口,其中5672是RabbitMQ的消息传递端口,15672是RabbitMQ的管理界面端口。-v /home/rabbitmq:/var/lib/rabbitmq
:将主机上的/home/rabbitmq目录挂载到容器内的/var/lib/rabbitmq目录,用于持久化存储RabbitMQ的数据。--hostname my-rabbitmq-host
:设置容器的主机名为my-rabbitmq-host。-e RABBITMQ_DEFAULT_VHOST=my_vhost
:设置RabbitMQ的默认虚拟主机为my_vhost。-e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin
:设置默认用户名和密码为admin/admin。--restart=always
:设置容器在启动时自动重启。rabbitmq:management
:使用rabbitmq:management镜像来运行容器,该镜像包含了RabbitMQ及其管理插件3.访问
然后就是访问了,但是在访问之前需要设置一下防火墙的相关配置...
防火墙设置好之后,开启那个rabbitmq的容器就好啦
现在就可以访问了
三.springboot连接配置
1.进入rabbitmq管理界面
然后输入密码之后就可以进入到里面啦
如果分不清页面上的东西,那么可以把这个页面翻译成中文的
2.创建用户
3.分配权限给用户
然后再退出登录,使用wh的这个账号登录一下
四.代码实现简单队列
1.创建一个生产者模块
它的父项目是一个空项目,下面是这个生产者模块选择的依赖
bashserver: port: 8888 spring: rabbitmq: host: 192.168.101.129 username: wh password: 123456 port: 5672 virtual-host: my_vhost connection-timeout: 0
2.创建一个消费者模块
其中用到的依赖跟上面是一样的
bashserver: port: 9999 spring: rabbitmq: host: 192.168.101.129 password: 123456 port: 5672 username: wh virtual-host: my_vhost
3.代码操作
(1)配置RabbitMQ消息队列
javapackage com.example.publisher; import org.springframework.amqp.core.Queue; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; // 使用@Configuration注解标记这是一个配置类 @Configuration // 忽略所有警告 @SuppressWarnings("all") public class RabbitConfig { // 定义一个名为firstQueue的方法,返回类型为Queue @Bean public Queue firstQueue() { // 创建一个新的Queue对象,名称为"firstQueue" return new Queue("firstQueue"); } }
(2)向消息队列发消息
javapackage com.example.publisher; import org.springframework.amqp.core.AmqpTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author是辉辉啦 * @create 2024-01-19-19:25 */ @RestController public class TestController { @Autowired private AmqpTemplate amqpTemplate; @RequestMapping("/send01") public String send01(){ //像消息队列发送消息 amqpTemplate.convertAndSend("firstQueue", "Hello World"); return "😙😙"; } @RequestMapping("/hh") public String hh(){ //像消息队列发送消息 return "😙😙"; } }
(3)连接rabbitmq测试
这时候就可以看到连接成功了
里面也多了一个新的队列
(4)RabbitMQ消息队列的消费者
javapackage com.example.consumer; import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.rabbit.annotation.RabbitHandler; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; // 定义一个名为Receiver的组件类,用于处理接收到的消息 @Component // 抑制所有警告信息 @SuppressWarnings("all") // 使用SLF4J日志框架进行日志记录 @Slf4j // 监听名为"firstQueue"的队列 @RabbitListener(queues = "firstQueue") public class Receiver { // 使用@RabbitHandler注解标记处理方法,该方法会在接收到消息时被调用 @RabbitHandler public void process(String msg) { // 记录接收到的消息内容 log.warn("接收到:" + msg); } }
其中可以接收到生产者的消息
(5)成自定义数据发送
这个user对象生产者模块和消费者模块都要放置...如果觉得麻烦可以建一个公共项目放置dto
javapackage com.example.publisher; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import java.io.Serializable; @SuppressWarnings("all") @Getter @Setter @AllArgsConstructor @NoArgsConstructor public class User implements Serializable { private String username; private String userpwd; }
①配置RabbitMQ消息队列
javapackage com.example.publisher; import org.springframework.amqp.core.Queue; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; // 使用@Configuration注解标记这是一个配置类 @Configuration // 忽略所有警告 @SuppressWarnings("all") public class RabbitConfig { // 定义一个名为firstQueue的方法,返回类型为Queue @Bean public Queue firstQueue() { // 创建一个新的Queue对象,名称为"firstQueue" return new Queue("firstQueue"); } // 定义一个名为secondQueue的方法,返回类型为Queue @Bean public Queue secondQueue() { // 创建一个新的Queue对象,名称为"secondQueue" return new Queue("secondQueue"); } }
②RabbitMQ消息队列的消费者
javapackage com.example.consumer; import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.rabbit.annotation.RabbitHandler; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; // 定义一个名为Receiver的组件类,用于处理接收到的消息 @Component // 抑制所有警告信息 @SuppressWarnings("all") // 使用SLF4J日志框架进行日志记录 @Slf4j // 监听名为"firstQueue"的队列 @RabbitListener(queues = "secondQueue") public class ModelReceiver { // 使用@RabbitHandler注解标记处理方法,该方法会在接收到消息时被调用 @RabbitHandler public void process(User user) { // 记录接收到的消息内容 log.warn("接收到:" + user); } }
成功
五.本篇问题总结
1.端口没开
在使用spring连接rabbitmq时,发现一直处于连接超时/拒绝连接的状态,后来发现是防火墙的端口没有开
启动防火墙
systemctl start firewalld
开放端口
firewall-cmd --zone=public --add-port=端口号/tcp --permanent
刷新防火墙规则
firewall-cmd --reload
查看防火墙列表
firewall-cmd --zone=public --list-ports
项目的端口以及rabbitmq的端口都需要开启
2.配置文件的层级关系
但是后面发现还是有问题,结果是配置文件的格式问题,这个rabbitmq是放在spring下面,一i的那个不要放错
3.配置文件中的信息核对
server.port
:指定了应用程序的HTTP端口号,这里设置为9999;spring.rabbitmq.host
:指定了RabbitMQ服务器的IP地址或主机名,这里设置为192.168.101.129;spring.rabbitmq.username
和spring.rabbitmq.password
:分别指定了连接RabbitMQ所使用的用户名和密码,这里设置为wh和123456;spring.rabbitmq.port
:指定了RabbitMQ服务的端口号,这里设置为5672;spring.rabbitmq.virtual-host
:指定了RabbitMQ的虚拟主机,以便在多个应用程序之间区分不同的队列和交换机,这里设置为my_vhost。还有就是要检查好自己的用户名与密码是否是对的,还有就是RabbitMQ服务器的IP地址或主机名一定要写对【自己的RabbitMQ安装在哪里就填写哪个的地址】,以及配置文件里面的东西都需要核对清楚
好啦,今天的分享就到这了,希望能够帮到你呢!😊😊