RabbitMQ 简介
MQ全称为Message Queue,即消息队列, RabbitMQ是由erlang语言开发,基于AMQP(Advanced MessageQueue 高级消息队列协议)协议实现的消息队列,它是一种应用程序之间的通信方法,消息队列在分布式系统开
发中应用非常广泛。RabbitMQ官方地址:http://www.rabbitmq.com/
开发中消息队列通常有如下应用场景:
1、任务异步处理。
将不需要同步处理的并且耗时长的操作由消息队列通知消息接收方进行异步处理。提高了应用程序的响应时间。
2、应用程序解耦合
MQ相当于一个中介,生产方通过MQ与消费方交互,它将应用程序进行解耦合。
市场上还有哪些消息队列?
ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ、Redis。
为什么使用RabbitMQ呢?
1、使得简单,功能强大。
2、基于AMQP协议。
3、社区活跃,文档完善。
4、高并发性能好,这主要得益于Erlang语言。
5、Spring Boot默认已集成RabbitMQ
其它相关知识
AMQP是什么 ?
AMQP是一套公开的消息队列协议,最早在2003年被提出,它旨在从协议层定义消息通信数据的标准格式,
为的就是解决MQ市场上协议不统一的问题。RabbitMQ就是遵循AMQP标准协议开发的MQ服务。
JMS是什么?
JMS是java提供的一套消息服务API标准,其目的是为所有的java应用程序提供统一的消息通信的标准,类似java的jdbc,只要遵循jms标准的应用程序之间都可以进行消息通信。它和AMQP有什么 不同,jms是java语言专属的消息服务标准,它是在api层定义标准,并且只能用于java应用;而AMQP是在协议层定义的标准,是跨语言的 。
RabbitMQ的工作原理
组成部分说明如下:
- Broker:消息队列服务进程,此进程包括两个部分:Exchange和Queue。
Exchange:消息队列交换机,按一定的规则将消息路由转发到某个队列,对消息进行过虑。
Queue:消息队列,存储消息的队列,消息到达队列并转发给指定的消费方。
- Producer:消息生产者,即生产方客户端,生产方客户端将消息发送到MQ。
- Consumer:消息消费者,即消费方客户端,接收MQ转发的消息。
消息发布接收流程:
—–发送消息—–
1、生产者和Broker建立TCP连接。
2、生产者和Broker建立通道。
3、生产者通过通道消息发送给Broker,由Exchange将消息进行转发。
4、Exchange将消息转发到指定的Queue(队列)
—-接收消息—–
1、消费者和Broker建立TCP连接
2、消费者和Broker建立通道
3、消费者监听指定的Queue(队列)
4、当有消息到达Queue时Broker默认将消息推送给消费者。
5、消费者接收到消息。
安装使用
下载安装
RabbitMQ由Erlang语言开发,Erlang语言用于并发及分布式系统的开发,在电信领域应用广泛,OTP(Open
Telecom Platform)作为Erlang语言的一部分,包含了很多基于Erlang开发的中间件及工具库,安装RabbitMQ需
要安装Erlang/OTP,并保持版本匹配,如下图:
RabbitMQ的下载地址:http://www.rabbitmq.com/download.html
erlang的下载地址:http://erlang.org/download/otp_win64_20.3.exe
这里使用:Erlang/OTP 20.3版本和RabbitMQ3.7.3版本。
特别提示
- 安装erlang和rabbitMQ以管理员身份运行。
- 当卸载重新安装时会出现RabbitMQ服务注册失败,此时需要进入注册表清理erlang搜索RabbitMQ、ErlSrv,将对应的项全部删除。
安装erlang
下载完成后,右键管理员运行安装,都是下一步安装完成即可。
配置erlang环境变量: ERLANG_HOME=D:\erl9.3 在path中添
加%ERLANG_HOME%\bin;
安装RabbitMQ
以管理员方式运行此文件,安装。
启动RabbitMQ
安装成功后会自动创建RabbitMQ服务并且启动。
1)从开始菜单启动RabbitMQ
RabbitMQ Service-install :安装服务
RabbitMQ Service-remove 删除服务
RabbitMQ Service-start 启动
RabbitMQ Service-stop 启动
2)通过命令启动RabbitMQ
1.安装并运行服务
rabbitmq-service.bat install 安装服务
rabbitmq-service.bat stop 停止服务
rabbitmq-service.bat start 启动服务
2.安装管理插件
安装rabbitMQ的管理插件,方便在浏览器端管理RabbitMQ
管理员身份运行命令: rabbitmq-plugins.bat enable rabbitmq_management
3.启动成功 登录RabbitMQ
进入浏览器,输入:http://localhost:15672
初始账号和密码:guest/guest
官方 Hello World 入门例子
官方各个语言集成RabbitMQ说明:https://www.rabbitmq.com/devtools.html
下面的例子我们暂时使用,javaClient的方式,通过导入amqp-client-5.7.2.jar完成例子的使用
我们先用 rabbitMQ官方提供的java client测试,目的是对RabbitMQ的交互过程有个清晰的认识。
参考 :https://github.com/rabbitmq/rabbitmq-java-client/
官网例子地址:https://www.rabbitmq.com/getstarted.html
创建maven工程-这里为了方面后面的集成,直接创建springboot项目
创建生产者工程和消费者工程,分别加入RabbitMQ java client的依赖。
test-rabbitmq-producer:生产者工程
test-rabbitmq-consumer:消费者工程
|
完整项目目录:
生产者
在生产者工程下的test中创建测试类如下:
|
消费者
|
测试
(1)启动消费者:发送消息
(2)查询RabbitMQ后台管理浏览器
(3)启动消费者
消息消费成功
已经变为了0
总结
1、发送端操作流程
1)创建连接
2)创建通道
3)声明队列
4)发送消息
2、接收端
1)创建连接
2)创建通道
3)声明队列
4)监听队列
5)接收消息
6)ack回复
通过代码我们不难发现,生产者和消费者的代码,其实前半段都是一模一样的。(创建连接工厂,创建连接,创建通道,声明队列)
RabbitMQ工作模式
RabbitMQ有以下几种工作模式 :
https://www.rabbitmq.com/getstarted.html
每后一个模式都能够实现前一个模式的功能
Work queues
work queues与入门程序相比,多了一个消费端,两个消费端共同消费同一个队列中的消息,而且它支持负载均衡的方式消费消息。
应用场景:对于任务过重或任务较多情况使用工作队列可以提高任务处理的速度(开启多个消费者消费同一个队列,处理相应的业务)。
案例
1、使用入门程序,启动多个消费者(启动多次即可)。
这里启动了两个消费者,都是监听helloworld队列。
2、生产者发送多个消息。
|
运行生产者
3.查看消费者输出
第一个消费者:
第二个消费者:
结果:
1、一条消息只会被一个消费者接收。
2、rabbit采用轮询的方式将消息是平均发送给消费者的。
3、消费者在处理完某条消息后,才会收到下一条消息。
Publish/subscribe
发布订阅模式:
1、每个消费者监听自己的队列。
2、生产者将消息发给broker,由交换机将消息转发到绑定此交换机的每个队列,每个绑定交换机的队列都将接收
到消息(也就是说,生产者发出的消息,每个队列都会收到。例如发出五个消息,那么每个队列都会收到五个)
案例
用户通知消费通知。当用户充值成功或转账完成系统通知用户,通知方式有短信、邮件多种方法 。
1.生产者代码
声明Exchange_fanout_inform交换机,声明两个队列并且绑定到此交换机,绑定时不需要指定routingkey,发送消息时不需要指定routingkey
|
2.邮件发送消费者
|
3.短信发送消费者
|
4.测试
1.启动消息生产者,发送消息
2.RabbitMQ的管理界面
查看交换机
单击进去
可以看到他绑定了两个队列
查看队列信息:
两个队列各有五条消息。
3.启动两个消费者
总结
1.使用生产者发送若干条消息,每条消息都转发到各各队列,每消费者都接收到了消息。
思考
publish/subscribe与work queues有什么区别和相似点。
区别:
1)work queues不用定义交换机(使用默认的交换机),而publish/subscribe需要定义交换机。
2)publish/subscribe的生产方是面向交换机发送消息,work queues的生产方是面向队列发送消息(底层使用默认交换机)。
3)publish/subscribe需要设置队列和交换机的绑定,work queues不需要设置,实质上work queues会将队列绑
定到默认的交换机 。
相同点:
两者实现的发布/订阅的效果是一样的,多个消费端监听同一个队列不会重复消费消息。
建议使用 publish/subscribe,发布订阅模式比工作队列模式更强大,并且发布订阅模式可以指定自己专用的交换
机。同时发布订阅模式,可以实现工作队列模式的功能(我们可以启动两个Consumer02_subscribe_sms消费者,然后他们都监听queue_inform_sms队列,当queue_inform_sms收到消息时他们会采用工作队列模式的轮循方式消费消息)
Routing
路由模式:
1、每个消费者监听自己的队列,并且设置routingkey。
2、生产者将消息发给交换机,由交换机根据routingkey来转发消息到指定的队列。
也就是说相比于发布订阅模式,他多了路由这个功能。
案例
通过rootingkey分别发送五条消息到sms队列和email队列
1.生产者代码
声明exchange_routing_inform交换机,声明两个队列并且绑定到此交换机,绑定时需要指定routingkey发送消息时需要指定routingkey
|
跟发布订阅模式的生产者相比代码的区别:
1.声明一个交换机时候,类型修改为BuiltinExchangeType.DIRECT 路由工作模式
2.在进行交换机和队列绑定的时候(channel.queueBind)多出了指明队列指定的rootingkey这一参数
3.发消息时,需要指明消息发送的rootingkey(也即是要发送到哪一个队列)
2.邮件消费者
|
3.短信消费者
|
4.测试
1.启动生产者,打开RabbitMQ的管理界面,观察交换机绑定情况:
使用生产者发送若干条消息,交换机根据routingkey转发消息到指定的队列。
总结
Routing模式和Publish/subscibe的区别
Routing模式要求队列在绑定交换机时要指定routingkey,消息会转发到符合routingkey的队列。
Topics
我们可以称它为加强版的Routing模式:
1、每个消费者监听自己的队列,并且设置带统配符的routingkey。
2、生产者将消息发给broker,由交换机根据routingkey来转发消息到指定的队列。
(星号) 只能替换 1 个条件。
(井号) 可替换 0 或多个条件。
案例
根据用户的通知设置去通知用户,设置接收Email的用户只接收Email,设置接收sms的用户只接收sms,设置两种通知类型都接收的则两种通知都有效。
1.生产者代码
声明交换机,指定topic类型:
关键代码
|
完整代码
|
分析一下规则:
在上面的代码中我们定义了下面两个通配符规则
|
#
可以匹配多个词,符号*可以匹配一个词语。
举例子:
inform.email 和 inform.sms 分别满足上面的ROUTINGKEY_EMAIL和ROUTINGKEY_SMS,所以消息各自发送到sms队列和email队列,因为#在这里是0个。
那么当inform.sms.email时,同时满足ROUTINGKEY_EMAIL和ROUTINGKEY_SMS,也就是说他把消息同时发送到sms队列和email队列。
2.邮件消费者
|
3.短信消费者
|
4.测试
1.启动生产者
查看浏览器控制台
查看生产者代码解释为什么各自有10条消息
使用生产者发送若干条消息,交换机根据routingkey统配符匹配并转发消息到指定的队列。所以这里两个队列各拥有10条消息。
总结
本案例的需求使用Routing工作模式能否实现
上面的案例的本质就是通过通配符的方式。我们可以使用Routing精确匹配也可实现。
使用Routing模式也可以实现本案例,共设置三个 routingkey,分别是email、sms、all,email队列绑定email和all,sms队列绑定sms和all,这样就可以实现上边案例的功能,实现过程比topics复杂。
Topic模式更多加强大,它可以实现Routing、publish/subscirbe模式的功能。
Header模式
header模式与routing不同的地方在于,header模式取消routingkey,使用header中的 key/value(键值对)匹配队列。
案例
根据用户的通知设置去通知用户,设置接收Email的用户只接收Email,设置接收sms的用户只接收sms,设置两种
通知类型都接收的则两种通知都有效。
1.生产者代码
队列与交换机绑定的代码与之前不同,如下:
|
|
2.邮件消费者
|
测试
RPC
RPC即客户端远程调用服务端的方法 ,使用MQ可以实现RPC的异步调用,基于Direct交换机实现,流程如下:
1、客户端即是生产者就是消费者,向RPC请求队列发送RPC调用消息,同时监听RPC响应队列。
2、服务端监听RPC请求队列的消息,收到消息后执行服务端的方法,得到方法返回的结果
3、服务端将RPC方法 的结果发送到RPC响应队列
4、客户端(RPC调用方)监听RPC响应队列,接收到RPC调用结果。
Spring整合RibbitMQ
我们选择基于Spring-Rabbit去操作RabbitMQ
https://github.com/spring-projects/spring-amqp
使用spring-boot-starter-amqp会自动添加spring-rabbit依赖,所以注释掉我们上面使用的java client方式引入的amqp-client依赖。
生产者修改
pom文件修改为
|
application.yml配置文件
|
定义RabbitConfig类,配置Exchange、Queue、及绑定交换机
这里以配置Topics模式为例子。
|
生产端
使用RarbbitTemplate发送消息
|
消费端者修改
修改pom文件
|
使用@RabbitListener注解监听队列
|