本章进行第一次RabbitMQ的基本使用,采用模块化的方式(模拟分布式),大概流程是:调用A服务A接口,A接口向消息队列中间件发送消息,又B服务的监听器去消费。初次学习,尚有不足。下载安装后会进行根据本人对消息队列的三大作用的理解进行一个demo的编写,下面开干。内含你可能也遇到的坑比问题。
一、概述
RabbitMQ是一个基于AMQP协议实现的消息队列中间件,可以实现异步处理,流量削峰,系统解耦,下面会进行一一阐述。
主要6种模式有:
- simple简单模式
- work工作模式(资源的竞争)
- publish/subscribe发布订阅(共享资源)
- routing路由模式
- topic 主题模式(路由模式的一种)
- rpc模式
后面会根据主题模式进行demo编写。
主题模式流程:
二、安装
安装是个坑,本人安装了特久,各种报错,差点被劝退在安装这一步。
注意:
1、电脑用户账号一定不能是中文,否则绝壁不行。
2、网上说的安装路径不能有空格和中文,但是即使没有(电脑账户是中文)也会报错。
3、启动rabbitmq默认是启动的C盘下面的路径下的文件,所以若C盘下存在中文肯定不行,需要在rabbitmq安装路径下sbin文件夹下执行指令修改启动执行文件的路径:
rabbitmq-service.bat remove
set RABBITMQ_BASE=XXX/YY
rabbitmq-service.bat install
XXX/YY是自己重新指定的一个启动路径,YY是自己新建的一个文件夹
4、下载插件,才可以进去rabbitmq管理界面,指令如下:
rabbitmq-plugins enable rabbitmq_management
5、下载rabbitmq之后可以在最近添加找到一个rabbitmq command prommpt,所有指令都可以在这个终端进行。
6、在如上终端运行net start rabbitmq,开启rabbitmq服务,我直接执行
或者进入cmd在sbin下执行该文件仍然报错,原因未知。
7、rabbitMQ是erlang语言开发,所以运行RabbitMQ之前必须下载版本合适的erlang。
8、注意RabbitMQ和erlang语言的版本对应,如下:
坑说完,下面开始下载安装。
1、下载安装erlang
2、下载安装rabbitMQ
安装过程就不讲了,网上教程很多,主要是讲讲坑。
三、简单使用并阐述三大作用
下面开始进行一个简单的使用,证实一下他的三大作用。
- 流量削峰
- 异步处理
- 系统解耦
未使用RabbitMQ
demo主要实现:
- 假设场景用户注册之后需要向数据库新增数据,然后调用第三方接口向用户注册所用手机号发送注册成功消息,然后调用第三方接口向用户注册所用邮箱发送注册成功邮件。
- 假设场景用户注销之后需要向数据库修改数据,然后调用第三方接口向用户注册所用手机号发送注销成功消息,然后调用第三方接口向用户注册所用邮箱发送注销成功邮件。
图如下:
代码结构如下:
此处只使用到框选处文件。
1、先修改yml配置文件,配置端口号,连接rabbitMQ
默认账号密码都是guest。
2、controller代码如下:
假设注册和注销时,短信通知和邮件通知都会耗时1秒钟。
3、使用postman调用接口进行测试
在接口内的三步操作顺序执行(改库、发短信、发邮件),并且注册和注销都需要做发送短信和邮件的操作,所有在注销和注册接口内都写了相关重复的逻辑(高耦合),并且若QPS数据量太大,直接访问接口会对服务器造成极大压力 ,严重的会造成宕机。
使用RabbitMQ
由此,引入RabbitMQ中间件进行改造,首先:
- 实现异步处理:上述代码可以得知,发送消息和发送邮件是同步执行,必须前面执行完后面才执行,但是根据需求,后者并不需要前者执行完才能执行,完全可以异步执行,异步执行可以大大减少消耗时间。并且用户只需要真实的注册和注销完成即可,通知只是次要的,所有接口里面实现库的操作即可,消息的操作直接交给消息监听器去处理即可。
- 实现系统解耦:上述代码可以得知,注册和注销都存在消息的处理(重复,高耦合),使用RabbitMQ可以将重复处理的代码交给消息监听器处理,接口只实现每个接口的核心代码即可。
- 实现流量削峰:当大量请求走向应用服务时,服务器压力太大,可以使用RabbitMQ,让请求先走向消息中间件,再让应用服务器去消费中间件里的消息。
下面开始通过代码实现:
图如下:
1、先建立模块化工程,模拟分布式,调用A服务接口,接口向RabbitMQ发送消息,B服务再去处理消息,减小A服务的服务器压力(模块化工程创建前面章节有讲到)。
目录结构如下:
provider服务编写测试接口,consumer服务编写消息监听器,处理后续逻辑,common编写其他服务所需要的公用模块。
2、采用主题模式实现消息队列功能,向父工程引入依赖,如下:
3、编写common模块代码
此常量类存放本次RabbitMQ测试所需要的所有配置值,便于管理。
4、修改provider服务的配置类,上面已经修改了
5、在provider服务新增一个controller类
相比上面的同步执行改库——发送消息——发送邮件,删除后面两步,引入rabbitTemplate,调用他的convertAndSend方法向交换机发送消息,使用常量里设置的交换机的值,和路由键的值。
路由键是6种模式中路由模式和主题模式所特有,而路由模式是绝对匹配,而主题模式是通配符匹配,此处讲讲通配符匹配规则:
通配符有#和*
#:可以匹配任意个数的元素
*:只能匹配一个元素
举例:#X*,可以匹配,X.1,1.X.1,1.1.1.X.1
此处:发送到交换机时的路由值设置的是topic.SMS.email,而队列绑定时的设置的路由键需要和这个相匹配,下面继续介绍
6、配置consumer服务的yml配置文件
7、在消费者服务创建topic配置,配置交换机和队列的绑定关系
注意加上Bean和Configuration注解,交给Spring管理。
创建一个交换机和两个队列(分别处理短信业务和邮件业务),并新建两个绑定关系,分别绑定两个通配符路由键,通过规则只要能匹配上生产者发送到交换机时配置的路由键,该队列即可获取到该交换机上面的消息。 例如:此时,
若假设绑定邮件队列的路由键修改成*.email.#,则该队列就收不到消息了,可以测试,我已经试过了,因为此时他只能匹配交换机中加X.email格式的消息,而存到交换机时设置的消息路由键是X.X.email。
注意:消息队列的配置需要加在消费者服务,因为若加在生产者服务,消费者服务的监听器在消费者服务一运行时就会进行监听,此时就会报错,所有加在消费者服务上,此时已经绑定好关系,即使队列为空,也不会报错。
8、新建两个监听器(监听邮件队列和短信队列)
取出生产者发送到消息队列的消息,判断类型是注册还是注销,然后走具体的处理。
@RabbitListener注解的类表示该类为监听器,参数为队列名称, @RabbitHandler表示该方法会去处理监听器获取的消息的逻辑。
9、演示效果:
使用postman调用注册和注销接口,如下:
核心代码部分一秒钟即可执行完成并返回结果。
而消费者服务在此后异步进行了短信逻辑和邮件逻辑的处理,如上图。
!!!!最后注意一点,坑到我的地方:
我误以为设置的通配符失效了,因为随便设置什么通配符,都可以匹配上交换机上的消息,研究了很久,发现是每次更改通配符之后,他都会往rabbitMQ服务上累加通配符,而不是以为的替换,如下,进入管理界面(http://localhost:15672/,账号密码默认都是guest):
点击如图,topic.message.SMS,进入该队列:
可以看到绑定了三个key,因为我修改key之后重新启动了服务,前两次正常匹配上,第三次照理说应该匹配不上的,结果还是匹配上了,研究半天,原来他的key值是叠加的,意味着只要其中一个key匹配的上交换机的路由key值,该队列就能获取消息。
——————————————————完毕——————————————————
后续会针对RabbitMQ的各种问题处理进行学习,有问题欢迎评论区讨论。