RabbitMQ消息对了核心概念以及部署使用

996 阅读10分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情

1.MQ消息队列的核心概念

1.1.什么是MQ消息队列

MQ的全称是Message Queue(消息队列),是在消息的传输过程中保存消息的容器,用于分布式系统之间进行通信,通信双方将请求写入到MQ消息队列中,被调用者从MQ中读取请求数据。

在传统情况下,系统之间的调用都是通过接口进行远程调用的,如下图所示,A系统通过远程接口调用B系统,两个系统之间会存在耦合性,当B系统出现异常时,A系统的业务逻辑将会失败,并且在高并发时,系统之间的频繁调用,对整体架构性能是有所影响的。 在这里插入图片描述

当程序架构中引入了MQ消息队列中间件之后,请求发送的一方(A系统)称之为生产者,将通信请求通过发布的方式写入到MQ消息队列中,被请求的接收方(B系统)称之为消费者,从MQ消息队列中通过订阅的方式拿到A系统发过来的通信请求,最终完成系统调用。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VF5RrKZj-1664502492319)(01RabbitMQ消息队列核心概念与部署.assets\image-20220307105249586.png)]

MQ消息队列的性能极高,高并发的情况下,请求写入MQ消息队列中,可以有效减轻被调用者的压力,从一定程度上实现了应用程序的解耦,A系统将请求写入MQ之后,业务逻辑就算完成了,等待B系统从MQ中获取信息完成整体系统的流程。

即使B系统挂掉了,也不会影响A系统的流程,B系统恢复后从MQ中依然可以读取到消息数据。

1.2.MQ消息队列的优势

MQ的优势在于:

  • 应用解耦:提高系统容错性和可维护性。
  • 异步处理:提高用户体验和系统吞吐量。
  • 削峰填谷:提高系统稳定性。

1)应用解耦

引入MQ之前

以电商平台为例,在传统的模式中,用户下单后,订单系统会调用库存系统、物流系统、支付系统,流程走完后用户才算下单完成,如果此时库存系统异常,订单系统与库存系统存在耦合性,业务逻辑调不通就会返回异常,从而导致用户下单失败。

并且在生产中,如果有新需求需要调用其他系统时,还需要经常性的修改订单系统的程序代码,添加新系统的调用,当不需要调用这个系统时也需要修改订单系统的程序代码,非常麻烦。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CgmU4NRi-1664502492320)(01RabbitMQ消息队列核心概念与部署.assets\image-20220307112945073.png)]

引入MQ之后

当架构中引入了MQ消息队列,可以有效的解决系统之间的耦合,从一定程度上实现应用解耦。

如下图所示,用户下单后,订单系统会将消息数据写入到MQ消息队列中,写入完成后就会返回给用户提示下单完成,库存系统、物流系统、支付系统再去MQ消息队列中消费订单系统发过来的消息数据,进行对应的业务逻辑,即使库存系统挂了,也不会影响用户的下单,并且在短时间内会迅速恢复,再从MQ中消费数据完成业务逻辑。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nCNcgLDm-1664502492321)(01RabbitMQ消息队列核心概念与部署.assets\image-20220307113756464.png)]

2)异步处理

引入MQ之前

在传统架构中,用户点击下单按钮,首先会将数据写入到数据库,大约花费20毫秒,然后去调用库存系统、物流系统、支付系统,使用同步的方式,调用完一个系统再调用一个系统,各花费300毫秒,最后返回给用户下单完成,总共耗时920毫秒,这种速度对于互联网项目而言属于比较慢的情况了,响应时间长就意味着负载高。

在这里插入图片描述

引入MQ之后

当引入MQ消息队列之后,用户的提交完订单后,将数据写入数据库花费20毫秒的时间,然后订单系统执行业务逻辑,不会直接调用其他系统,而是将调用的消息数据写入到MQ消息队列中,花费5毫秒时间,写入MQ之后,就会返回给用户已经下单完成了,此时其他系统再从MQ消息队列中消费订单系统的消息数据,完成整个业务流程。

在这里插入图片描述

3)削峰填谷

削峰填谷指的是流量高峰期,引入MQ的变化趋势,大流量由MQ接收,相当于高峰被削了一半,流量全部导到MQ就相当于填谷,最后由应用程序从MQ中消费数据。

如果流量高并发的时候,架构中没有MQ消息队列,那么用户的所有流量请求都会直接发生到应用程序,应用程序的并发量可能达不到用户的请求量,就会导致程序崩溃。

当架构中引入了MQ消息队列,那么用户的大量请求会被MQ接收,然后由应用程序通过规则从MQ中消费请求,在减轻应用程序压力的同时提高了网站的稳定性。 在这里插入图片描述

1.3.MQ消息队列的劣势

MQ消息队列的功能很强单,但是也存在一定的劣势。

  • 系统可用性降低
    • 系统引入外部中间件越多,系统的稳定性也会降低,如果MQ宕机,就会对整个业务平台造成影响。
  • 系统复杂度提高
    • MQ的加入大大增大了系统的复杂度,之前是远程直接调用,现在需要通过MQ进行异步调用,还需要避免消息不会被重复消费、消息传递的顺序性、消息丢失情况。
  • 消息一致性问题
    • 使用MQ还会出现消息不一致的问题,例如A系统通过MQ给B、C、D系统发送消息数据,B、C系统处理成功,D系统处理失败等等。

1.4.什么场景下使用MQ消息队列

在生产环境中,什么场景下需要使用MQ消息队列,什么情况下需要直接远程调用?

适合直接远程调用的场景:

1、生产者需要消费者获取反馈信息,例如A系统调用B系统,需要B系统返回一个参数,B系统带着这个参数去请求C系统,此时就无法通过MQ传递消息了,只能通过远程调用。

2、不允许各系统间的数据不一致。

适合使用MQ的场景:

1、生产者不需要从消费者出获取反馈。

2、允许短暂的不一致性,消费者从MQ中读取消息需要一定的时间处理。

3、明确要求实现应用解耦、提速、削峰的需求。

1.4.常见的MQ消息队列产品

在这里插入图片描述

2.RabbitMQ消息队列概述

2.1.AMQP协议概念

消息队列使用的协议AMQP,即Advanced Message Queuing Protocol(高级消息队列协议),AMQP协议是一种网络协议,应用成协议的一种,面向消息中间件设计的协议标准,基于此协议的客户端与中间件可以相互传递消息数据,不受客户端/中间件产品不同的限制,是一种通用的协议标准。

AMQP协议如下图所示:Publisher是生产者,Exchange是传输数据的交换机,Queue是存放消息数据的容器,Consumer是消费者。 在这里插入图片描述

传输一条消息数据的流程:首先由Publisher(生产者)通过publish方式将消息传输到中间件的Exchange(交换组件),Exchange通过路由的方式将消息数据存储在Queue队列中,最后由Consumer(消费者)通过Consumers方式从Queue队列中消费数据。

2.2.RabbitMQ架构原理

RabbitMQ通过Erlang语言开发,性能强。

RabbitMQ架构与工作原理:

RabbitMQ架构与AMQP架构类似,Producer(生产者)、Consumer(消费者)都与Broker(RabbitMQ消息中间件)建立TCP连接,频繁建立TCP连接对资源消耗有所影响,RabbitMQ在客户端连接方面提供了channel(管道)方式与服务端建立连接,在RabbitMQ的Broker中会有多个VirtualHost(虚拟主机),多个VirtualHost之间相互隔离,在每隔VirtualHost中包含了多个Exchange和Queue,每个Exchange通过Binding与Qqueue进行绑定。

生产者通过channel与RabbitMQ建立连接,将消息数据通过Exchange路由到Queue队列中,消费者通过Channel与RabbitMQ建立连接,从Queue中读取消息数据。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D4uA5ErN-1664502492324)(01RabbitMQ消息队列核心概念与部署.assets\rabbitmq架构图.png)]

RabbitMQ各组件介绍:

  • Broker
    • 接收和分发消息的应用,RabbitMQ叫做Message Broker。
  • Virtual Host
    • 出于多租户和安全因素设计,把AMQP的基本组件划分到一个虚拟的分组中,类似于命名空间的概念,多个VirtualHost之间存在网络隔离。
  • Connection
    • 发布者和消费者与MQ之间建立TCP连接。
  • Channel
    • 如果每一次访问RabbitMQ都需要建立一个连接,在消息量大的时候TCP连接消耗资源太大,效率也低,Channel是在Connection内部建立的逻辑连接,如应用程序支持多线程,通常每个线程都会创建单独的Channel进行通信。
  • Exchange
    • 消息数据到达MQ的第一站,根据路由分发规则,匹配对应的Queue,将消息存储在Queue队列中。
    • 常用的类型有direct、topic
  • Queue
    • 消息最终被存储在Queue队列中,等待消费者读取
  • Binding
    • Exchange和Queue之间的绑定

RabbitMQ的工作模式包含简单模式、work queues、发布订阅模式、路由模式、Topics主题模式等等。

JAVA程序连接RabbitMQ需要通过JMS接口,JMS是JavaEE规范的一种,类似于JDBC接口,RabbitMQ官方没有提供JMS接口,但是开源社区有RabbitMQ的JMS实现包。

2.3.RabbitMQ与Erlang版本对照表

RabbitMQ versionMinimum required Erlang/OTPMaximum supported Erlang/OTP
3.8.1623.224.x
3.8.15、3.8.14、3.8.13、3.8.12、3.8.11、3.8.10、3.8.922.323.x
3.8.8、3.8.7、3.8.6、3.8.5、3.8.421.323.x
3.8.3、3.8.2、3.8.1、3.8.021.322.x
3.7.27、3.7.26、3.7.25、3.7.24、3.7.23、3.7.22、3.7.21、3.7.20、3.7.1921.322.x
3.7.18、3.7.17、3.7.16、3.7.1520.322.x
3.7.14、3.7.13、3.7.12、3.7.1120.321.x
3.7.10、3.7.9、3.7.8、3.7.719.321.x
3.7.6、3.7.5、3.7.4、3.7.3、3.7.2、3.7.1、3.7.019.320.x

3.RabbitMQ官网使用

RabbitMQ的官网十分详细,每种技术都可以在官网上找到解决方案。

官网地址:www.rabbitmq.com/

1)点击Get Started进入使用说明页面。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SY0AlxZQ-1664502492324)(01RabbitMQ消息队列核心概念与部署.assets\image-20220308100312779.png)]

2)Download+Installation表示下载和安装,RabbitMQ Tutorials是文档操作手册

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AcasUXLI-1664502492325)(01RabbitMQ消息队列核心概念与部署.assets\image-20220308100151956.png)]

3)RabbitMQ支持Docker部署。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uTjITh9j-1664502492326)(01RabbitMQ消息队列核心概念与部署.assets\image-20220308100440439.png)]

4.使用RPM包的方式部署RabbitMQ消息队列

4.1.安装Erlang环境

RabbitMQ 3.7.10版本需要依赖Erlang 19.3以上的版本。

1.安装依赖软件
[root@rabbitmq ~]# yum -y install build-essential openssl openssl-devel unixODBC-devel make gcc gcc-c++ kernel-devel m4 ncurses-devel tk tc xz

2.安装erlang
[root@rabbitmq ~]# rpm -ivh erlang-19.3.6.4-1.el6.x86_64.rpm 
警告:erlang-19.3.6.4-1.el6.x86_64.rpm: 头V4 RSA/SHA1 Signature, 密钥 ID 6026dfca: NOKEY
准备中...                          ################################# [100%]
正在升级/安装...
   1:erlang-19.3.6.4-1.el6            ################################# [100%]

3.查看erlang的版本
[root@rabbitmq ~]# erl -version
Erlang (SMP,ASYNC_THREADS,HIPE) (BEAM) emulator version 8.3.5.3
[root@rabbitmq rabbitmq]# systemctl start rabbitmq-server

4.2.部署RabbitMQ消息队列

1.安装socat
[root@rabbitmq rabbitmq]# yum -y install socat

2.下载RabbitMQ rpm包
[root@rabbitmq rabbitmq]# wget https://repo.huaweicloud.com/rabbitmq-server/v3.7.10/rabbitmq-server-3.7.10-1.el7.noarch.rpm

3.安装RabbitMQ
[root@rabbitmq rabbitmq]# rpm -ivh rabbitmq-server-3.7.10-1.el7.noarch.rpm 
警告:rabbitmq-server-3.7.10-1.el7.noarch.rpm: 头V4 RSA/SHA1 Signature, 密钥 ID 6026dfca: NOKEY
准备中...                          ################################# [100%]
正在升级/安装...
   1:rabbitmq-server-3.7.10-1.el7     ################################# [100%]

4.3.开启RabbitMQ后台管理系统

1.开启后台管理系统
[root@rabbitmq ~]# rabbitmq-plugins enable rabbitmq_management
Enabling plugins on node rabbit@elkstack-3:
rabbitmq_management
The following plugins have been configured:
  rabbitmq_management
  rabbitmq_management_agent
  rabbitmq_web_dispatch
Applying plugin configuration to rabbit@elkstack-3...
The following plugins have been enabled:
  rabbitmq_management
  rabbitmq_management_agent
  rabbitmq_web_dispatch

started 3 plugins.

2.开放登陆用户
[root@rabbitmq ~]# vim /usr/lib/rabbitmq/lib/rabbitmq_server-3.7.10/ebin/rabbit.app 
            {loopback_users, [guest]},					#39行,将默认的<<"guest">>改成guest

4.4.启动RabbitMQ

1.启动RabbitMQ
[root@rabbitmq ~]# systemctl start rabbitmq-server.service 
[root@rabbitmq ~]# systemctl enable rabbitmq-server.service

2.查看RabbitMQ的端口号
[root@rabbitmq ~]# netstat -lnpt | grep beam
tcp        0      0 0.0.0.0:25672           0.0.0.0:*               LISTEN      13321/beam.smp      
tcp        0      0 0.0.0.0:15672           0.0.0.0:*               LISTEN      13321/beam.smp      
tcp6       0      0 :::5672                 :::*                    LISTEN      13321/beam.smp 
#25672是集群通信端口 15672是后台管理系统端口 5672是程序连接MQ使用的端口

4.5.访问RabbitMQ的后台管理系统

访问服务器的5672端口进入MQ的后台管理系统,账号密码都是guest。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I4bu7oKo-1664502492327)(01RabbitMQ消息队列核心概念与部署.assets\image-20220308120342419.png)]

MQ后台管理系统界面如下。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9cMeCqLa-1664502492327)(01RabbitMQ消息队列核心概念与部署.assets\image-20220308154118670.png)]