消息中间件RabbitMQ
1. MQ 的相关概念
1.1 什么是MQ
MQ全称为Message Queue,消息队列是应用程序和应用程序之间的通信方法。
本质是个队列,数据是先入先出,只不过队列中存放的内容是 message 而已,还是一种跨进程的通信机制,用于上下游传递消息。在互联网架构中,MQ 是一种非常常 见的上下游“逻辑解耦+物理解耦”的消息通信服务。使用了 MQ 之后,消息发送上游只需要依赖 MQ,不 用依赖其他服务。
1.2 为什么要用MQ
我公司是跨境电商公司,我就用电商的系统为例吧,我公司通过自己开发的ERP系统和第三方电商平台进行订单、库存、物流、支付等系统的数据对接。
就在19年的双十一,公司的ERP挂了,十多万订单没有导进ERP系统,导致公司仓库物流基本瘫痪,研发部门全部受到了处罚。
开发中消息队列通常有如下应用场景:
1、任务异步处理
在项目中,可将一些无需即时返回且耗时的操作提取出来,进行异步处理,而这种异步处理的方式大大的节省了服务器的请求响应时间,从而提高了系统的吞吐量。
例如 A 调用 B,B 需要花费很长时间执行,但是 A 需要知道 B 什么时候可 以执行完,以前一般有两种方式,A 过一段时间去调用 B 的查询 api 查询。或者 A 提供一个 callback api, B 执行完之后调用 api 通知 A 服务。这两种方式都不是很优雅,使用消息总线,可以很方便解决这个问题, A 调用 B 服务后,只需要监听 B 处理完成的消息,当 B 处理完成后,会发送一条消息给 MQ,MQ 会将此 消息转发给 A 服务。这样 A 服务既不用循环调用 B 的查询 api,也不用提供 callback api。同样 B 服务也不 用做这些操作。A 服务还能及时的得到异步处理成功的消息。
2、应用程序解耦合
MQ相当于一个中介,生产方通过MQ与消费方交互,它将应用程序进行解耦合。
用户创建订单后,如果耦合调用库存系统、物流系统、支付系统,任何一个子系统出了故障,都会造成下单操作异常。当转变成基于消息队列的方式后,系统间调用的问题会减少很多,比如物流系统因为发生故障,需要几分钟来修复。在这几分钟的时间里,物流系统要处理的内存被缓存在消息队列中,用户的下单操作可以正常完成。当物流 系统恢复后,继续处理订单信息即可,中单用户感受不到物流系统的故障,提升系统的可用性。
3、削峰填谷
如订单系统,在下单的时候就会往数据库写数据。但是数据库只能支撑每秒1000左右的并发写入,并发量再高就容易宕机。低峰期的时候并发也就100多个,但是在高峰期时候,并发量会突然激增到5000以上,这个时候数据库肯定卡死了。
消息被MQ保存起来了,然后系统就可以按照自己的消费能力来消费,比如每秒1000个数据,这样慢慢写入数据库,这样就不会卡死数据库了。
但是使用了MQ之后,限制消费消息的速度为1000,但是这样一来,高峰期产生的数据势必会被积压在MQ中,高峰就被“削”掉了。但是因为消息积压,在高峰期过后的一段时间内,消费消息的速度还是会维持在1000QPS,直到消费完积压的消息,这就叫做“填谷”
2. RabbitMQ
2.1 RabbitMQ的概念
RabbitMQ 是一个消息中间件:它接受并转发消息。你可以把它当做一个快递站点,当你要发送一个包 裹时,你把你的包裹放到快递站,快递员最终会把你的快递送到收件人那里,按照这种逻辑 RabbitMQ 是 一个快递站,一个快递员帮你传递快件。RabbitMQ 与快递站的主要区别在于,它不处理快件而是接收, 存储和转发消息数据。
RabbitMQ官方地址:http://www.rabbitmq.com/
RabbitMQ提供了6种模式:简单模式,work模式,Publish/Subscribe发布与订阅模式,Routing路由模式,Topics主题模式,RPC远程调用模式(远程调用,不太算MQ;暂不作介绍);
官网对应模式介绍:https://www.rabbitmq.com/getstarted.html
2.2 四大核心概念
生产者
产生数据发送消息的程序是生产者
交换机
交换机是 RabbitMQ 非常重要的一个部件,一方面它接收来自生产者的消息,另一方面它将消息 推送到队列中。交换机必须确切知道如何处理它接收到的消息,是将这些消息推送到特定队列还是推送到多个队列,亦或者是把消息丢弃,这个得有交换机类型决定
队列
队列是 RabbitMQ 内部使用的一种数据结构,尽管消息流经 RabbitMQ 和应用程序,但它们只能存储在队列中。队列仅受主机的内存和磁盘限制的约束,本质上是一个大的消息缓冲区。许多生产者可以将消息发送到一个队列,许多消费者可以尝试从一个队列接收数据。这就是我们使用队列的方式
消费者
消费与接收具有相似的含义。消费者大多时候是一个等待接收消息的程序。请注意生产者,消费 者和消息中间件很多时候并不在同一机器上。同一个应用程序既可以是生产者又是可以是消费者。
2.3 RabbitMQ核心部分
2.4 各个名词介绍
Broker:接收和分发消息的应用,RabbitMQ Server 就是 Message Broker
Virtual host:出于多租户和安全因素设计的,把 AMQP 的基本组件划分到一个虚拟的分组中,类似 于网络中的 namespace 概念。当多个不同的用户使用同一个 RabbitMQ server 提供的服务时,可以划分出 多个 vhost,每个用户在自己的 vhost 创建 exchange/queue 等
Connection:publisher/consumer 和 broker 之间的 TCP 连接
Channel:如果每一次访问 RabbitMQ 都建立一个 Connection,在消息量大的时候建立 TCP Connection 的开销将是巨大的,效率也较低。Channel 是在 connection 内部建立的逻辑连接,如果应用程 序支持多线程,通常每个 thread 创建单独的 channel 进行通讯,AMQP method 包含了 channel id 帮助客 户端和 message broker 识别 channel,所以 channel 之间是完全隔离的。Channel 作为轻量级的 Connection 极大减少了操作系统建立 TCP connection 的开销
Exchange:message 到达 broker 的第一站,根据分发规则,匹配查询表中的 routing key,分发 消息到 queue 中去。常用的类型有:direct (point-to-point), topic (publish-subscribe) and fanout (multicast)
Queue:消息最终被送到这里等待 consumer 取走
Binding:exchange 和 queue 之间的虚拟连接,binding 中可以包含 routing key,Binding 信息被保 存到 exchange 中的查询表中,用于 message 的分发依据
2.5 安装
1.官网地址
https://www.rabbitmq.com/download.html
安装大家百度就行了,这个要看你是什么系统,只要注意版本不要冲突就行了
可以看到我的版本是没有冲突的
2.常用命令(按照以下顺序执行)
添加开机启动 RabbitMQ 服务
chkconfig rabbitmq-server on
service rabbitmq-server start–开启
service rabbitmq-server stop–关闭
service rabbitmq-server status–查看当前运行状态
3. 开启 web 管理插件
rabbitmq-plugins enable rabbitmq_management
此时通过ip:15672就能打开web 管理页面
如果没有的话,可能是防火墙没关闭,直接关闭浏览器就行了。
如果还不行,那么问题可能就有点麻烦了
输入rabbitmq-plugins list
正常启动的服务应该是这样,E和e分别表示显性和隐性启动:
如果不是这个样子,输入rabbitmq-plugins enable rabbitmq_management启动插件通常即可解决80%的问题.如果还是解决不了或者是本来就已经启动插件的情况继续第2步.
2.继续输入rabbitmqctl start_app
显示错误可能有三种:
1)目标节点无法访问(例如,由于主机名解析,TCP连接或防火墙问题)
2)CLI工具无法通过服务器进行身份验证(例如,由于CLI工具的Erlang cookie与服务器不匹配)
3)目标节点未运行
对应的解决办法:
1)ping一下主机地址看能不能ping通,不通就是地址有问题或者主机有问题,;检查防火墙是否拦截以及mq需要的端口号能否使用(方法请自行百度,因为一般都不是这个问题就不赘述了)
2)身份验证没有通过,都有哪些情况我不清楚
3)此外可以查询官方文档https://www.rabbitmq.com/plugins.html
4.添加一个新的用户
用默认账号密码(guest)访问地址 http://47.115.185.244:15672/出现权限问题
我们先查看下当前已有的用户
查询当前用户和角色
rabbitmqctl list_users
创建账号
rabbitmqctl add_user admin 123
设置用户角色
rabbitmqctl set_user_tags admin administrator
设置用户权限 set_permissions [-p <vhostpath>] <user> <conf> <write> <read>
执行下面这句话就行
rabbitmqctl set_permissions -p “/” admin “.*” “.*” “.*”
用户 user_admin 具有/vhost1 这个 virtual host 中所有资源的配置、写、读权限
5.再次利用 admin 用户登录
6. 其他命令
关闭应用的命令为rabbitmqctl stop_app
清除的命令为 rabbitmqctl reset
重新启动命令为 rabbitmqctl start_app
3. Hello World
这是MQ中最简单的一种模式了,我们就用这个模式来入门。
在下图中,“ P”是我们的生产者,“ C”是我们的消费者。中间的框是一个队列-RabbitMQ 代 表使用者保留的消息缓冲区
3.1 依赖
maven项目大家总会创建吧,这里就随便你们发挥了。
<!--指定 jdk 编译版本--> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>8</source> <target>8</target> </configuration> </plugin> </plugins> </build> <dependencies> <!--rabbitmq 依赖客户端--> <dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-client</artifactId> <version>5.8.0</version> </dependency> <!--操作文件流的一个依赖--> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency> </dependencies>