一、RabbitMQ是什么 ?
RabbitMQ是用Erlang实现的一个高并发高可靠AMQP消息队列服务器。支持消息的持久化、事务、拥塞控制、负载均衡等特性,使得RabbitMQ拥有更加广泛的应用场景。RabbitMQ跟Erlang和AMQP有关。下面简单介绍一下Erlang和AMQP。
Erlang是一门动态类型的函数式编程语言,它也是一门解释型语言,由Erlang虚拟机解释执行。从语言模型上说,Erlang是基于Actor模型的实现。在Actor模型里面,万物皆Actor,每个Actor都封装着内部状态,Actor相互之间只能通过消息传递这一种方式来进行通信。对应到Erlang里,每个Actor对应着一个Erlang进程,进程之间通过消息传递进行通信。相比共享内存,进程间通过消息传递来通信带来的直接好处就是消除了直接的锁开销(不考虑Erlang虚拟机底层实现中的锁应用)。
AMQP(Advanced Message Queue Protocol)定义了一种消息系统规范。这个规范描述了在一个分布式的系统中各个子系统如何通过消息交互。而RabbitMQ则是AMQP的一种基于erlang的实现。AMQP将分布式系统中各个子系统隔离开来,子系统之间不再有依赖。子系统仅依赖于消息。子系统不关心消息的发送者,也不关心消息的接受者。
二、现存问题
2.1.服务调用
服务调用:两个服务调用时,可以通过传统的HTTP方式,让服务A直接去调用服务B的接口,但是这种方式是同步的方式,虽然可以采用SpringBoot提供的@Async注解实现异步调用,但是这种方式无法确保请求一定回访问到服务B的接口。那如何保证服务A的请求信息一定能送达到服务B去完成一些业务操作呢?如何实现异步调用?
2.2.海量请求
海量请求:在我们在做一些秒杀业务时,可能会在某个时间点突然出现大量的并发请求,这可能已经远远超过服务器的并发瓶颈,这时我们需要做一些削峰的操作,也就是将大量的请求缓冲到一个队列中,然后慢慢的消费掉。如何提供一个可以存储千万级别请求的队列呢?
2.3.微服务调用
在微服务架构下,可能一个业务会出现同时调用多个其他服务的场景,而且这些服务之间一般会用到Feign的方式进行轻量级的通讯,如果存在一个业务,用户创建订单成功后,还需要去给用户添加积分、通知商家、通知物流系统、扣减商品库存,而在执行这个操作时,如果任意一个服务出现了问题,都会导致整体的下单业务失败,并且会导致给用户反馈的时间延长。这时就造成了服务之间存在一个较高的耦合性的问题。如何可以降低服务之间的耦合性呢?
三、解决方案
上述的问题就需要通过RabbitMQ解决
3.1.服务调用
服务之间如何想实现可靠的异步调用,可以通过RabbitMQ的方式实现,服务A只需要保证可以把消息发送到RabbitMQ的队列中,服务B就一定会消费到队列中的消息只不过会存在一定的延时。
3.2.海量数据
突然的海量请求可以存储在RabbitMQ的队列中,然后由消费者慢慢消费掉,RabbitMQ的队列本身就可以存储上千万条消息
3.3.微服务调用
在调用其他服务时,如果允许延迟效果的出现,可以将消息发送到RabbitMQ中,再由消费者慢慢消费|
四、RabbitMQ安装
这里推荐搭建采用Docker的方式在Linux中安装RabbitMQ,
4.1.拉取 RabbitMQ 镜像
这里选择的版本是 rabbitmq:3.12-management在终端中执行以下命令以拉取 rabbitmq:3.12-management根据自己使用过的版本:
镜像尽量选择 带-management后缀的,因为这个是自带Web监控页面,同3.12版本MQ有两个
docker pull rabbitmq:3.12-management #推荐使用
docker pull rabbitmq:3.12 #这个是不带Web管理页面的,是需要自己手动安装插件
4.2.创建并运行容器
使用以下命令创建一个新的 rabbitmq容器并将其启动:
docker run --name myrabbitmq -p 5672:5672 -p 15672:15672 -d rabbitmq:3.12-management
参数说明:
- --name 是 容器别名,
- 将 宿主机 5672端口映射到 容器内5672,
- 端口15672端口映射到 容器内15672 端口,
- 访问宿主机端口的时候会映射到对应容器端口,
- -d 表示后台运行。
4.3.RabbitMQ 常用端口以及作用
- 5672端口:AMQP(Advanced Message Queuing Protocol)协议的默认端口,用于客户端与RabbitMQ服务器之间的通信。
- 15672端口:RabbitMQ的管理界面,默认使用HTTP协议,用于监控和管理RabbitMQ服务器。
- 4369端口:Erlang分布式节点通信端口,用于RabbitMQ节点之间的通信。
- 25672端口:Erlang分布式节点通信端口,用于集群中的内部通信。
- 5671端口:安全的AMQP端口,使用TLS/SSL进行加密通信。
4.4.访问 管理页面测试,是否启动成功
访问 localhost:15672
管理页面是否正常
http://服务器ip地址:15672/
RabbitMQ默认的登录账号和密码如下:
- 用户名:guest
- 密码: guest
访问如下:
登录后如下图:
五、RabbitMQ构架
RabbitMQ的架构可以查看官方地址:https://rabbitmq.com/tutorials/amqp-concepts.html
从上图可以看出RabbitMQ中主要分为三个角色:
- Publisher:消息的发布者,将消息发布到RabbitMQ中的Exchange(交换机)
- RabbitMQ服务:Exchange接收Publisher的消息,并且根据Routes策略将消息转发到Queue(队列)中
- Consumer:消息的消费者,监听Queue中的消息并进行消费
官方提供的架构图相对简洁,我们可以自己画一份相对完整一些的架构图:
上图说明:
- Publisher和Consumer都是单独和RabbitMQ服务中某一个Virtual Host建立Connection的客户端
- 后续通过Connection可以构建Channel通道,用来发布、接收消息
- Channel 是在 connection内部建立的逻辑连接,如果应用程序支持多线程,通常每个thread创建单独的 channel 进行通讯,AMQP method包含了channel id帮助客户端和message broker识别channel,所以channel 之间是完全隔离的。Channel 作为轻量级的Connection极大减少了操作系统建
- 一个Virtual Host中可以有多个Exchange和Queue,Exchange可以同时绑定多个Queue
- RabbitMq的VirtualHost(虚拟消息服务器),每个VirtualHost相当于一个相对独立的RabbitMQ服务器;
- 每个VirtualHost之间是相互隔离的,exchange、queue、message不能互通。
在基于架构图再看图形化界面如下: