多种MQ的探究-RocketMQ
RocketMQ
原理
简介:
集群图(来源于网络):
name-server:用来实时更新发现broker的服务,可多节点,节点互相不通信。
broker:分为master、slave,可布集群,启动时将自己注册到name-server上,每个节点会心跳反馈到name-server上。
producer:消息创建者,定时向name-server获取topic
consumer:消息消费者,定时向name-server获取topic
优缺点:
rocketMQ支持分布式部署,支持大吞吐量的应用开发。
提供mq、db等多方事务一致性。
目前阿里在用,而且拥有自己封装的多套MQ分支。
对于中小型系统来说,架构过于庞大。
原理
rocketmq提供多种推送方式:异步、同步、延时等等。
rocketmq的结构:
group–>多个topic–>多个queue
说明:
一个group对应多个topic,一个topic对应多个queue,activemq会进行分片处理,一个topic可以分片到不同的broker上,这里的queue与activemq的queue是两个概念,并不是点对点的队列,我们知道topic在一个broker的一个分片会依据消费者的数量进行负载均衡的分组,而queue就是这个组,是消息资源分配的基本单元。
rocketmq初始化:
rocketmq在启动nameserver与broker的时候,nameserver会收录集群中所有broker注册过来的信息(包含topic及topic下的queue)以及producer初始化的topic信息。这时nameserver会形成topic-broker的关联信息群,并且broker会进行间隔与nameserver进行交互检测是否有效(称为:心跳检测,默认30秒,2分钟未进行检测则默认broker下线)
producer:
producer会与一台nameserver建立长链接,然后定时间隔获取broker、topic信息,然后与对应的broker建立长链接,消息推送时会推送到所关联的所有broker上。
consumer:
consumer与producer一致,会与一台nameserver建立长链接,然后获取broker、topic信息,然后与对应的broker建立长链接,然后注册监听器,不断地拉取最新消息。
rocketmq的推送流程:
producer携带topic、group将message推送到broker上,这时会负载到所有拥有该topic的broker分片上面,然后consumer监听到对应的broker上topic存在消息,则会主动拉取消息进行消费。
- 消息推送:
在rocketmqTemplate集成了AbstractMessageSendingTemplate类,此类包含了与activemq一致的推送方式convertAndSend(D destination, Object payload),直接使用主题与message内容进行推送,详细可参考顶部activemq推送流程查看,或者大佬们可以跟进代码看一下源码。
首先,rocketmq根据headers与消息内容创建消息对象,如果headers为空,会使用默认(conversionHint)值。
然后,依据主题进行推送:
推送首先会获取一个broker投放消息(异步会有重试机制的校验):
这个selectOneMessageQueue()方法就是选取broker的机制,如果只有一个broker则直接使用get(0):
如果多个broker,则随即排序列表(collections.shuffle:使用随机源对指定列表进行置换,所有置换发生的可能性都是大致相等的),然后根据奇偶算法获取一个broker:
ps:获取完broker,后续还有个校验是否是最好的broker进行write。
之后,会获取broker的address,然后设置请求的header信息:
最后调用客户端推送消息:
再往下就是关于socket流的使用,大家想看的可以继续跟下去。
- 消息消费
消息的消费主要通过监听器来实现,首先我们会加入这个注解,参数主要有group与topic(此时是初始化好了name-server,详细的配置还有accessKey与secreKey):
监听到消息后会进行消费,而我们只需要实现接口RocketMQListener.onMessage()即可:
至于消息监听在服务启动的时候会启动注册:
类型默认TAG:
安装
首先去官网下载最新的包:
http://rocketmq.apache.org/dowloading/releases/
官网有安装教程quick start
官网提供两类文件以供下载:
source为源码,需要手动编译打包:
bin可以直接使用,解压后直接进入/bin目录(unzip xxx.zip),我们可以看到rocketmq的所有脚本命令。
然后分别启动namesrv和broker:
nohup sh mqnamesrv &
nohup sh bin/mqbroker -n localhost:9876 &
(停止脚本命令:sh mqshutdown broker、sh mqshutdown namesrv)
出现上述日志表示启动成功,这里再说下启动的配置:
- runserver.sh:
-server后面配置的参数依据需要调整,笔者安装后默认都是4G 8G,本地机器根本吃不消,故调整为256m。 - runbroker.sh:
-server的配置与runserver.sh一致,依据需要调整。
启动完成后,我们可以看下broker的详细参数(sh mybroker -m):
namesrvAddr:rocketmq的服务名,包含ip端口,不指定详细ip可使用0.0.0.0或localhost或127.0.0.1。
brokerIP1:broker的ip
autoCreateTopicEnable=true:是否允许自动创建主题,这个要保证true才能自定义topic,否则就需要在配置中定死topic(例如在rocketmq-console中直接创建新的topic),如果没有配置,且自定义的主题在rocketmq中不存在就会报错:no route topic。
查看启动的应用:
应用
老版本rocketmq开发这里就不赘述了,笔者主要讲述一下关于springboot集成的rocketmq是如何开发的,首先创建一个独立的组件rocketmq工程,发现在springboot2.2这个版本依旧搜索不到rocketmq的starter,故找到了rocketmq官方githup:
https://github.com/apache/rocketmq-spring
官方提供了对springboot的支持:
目前最新版2.0.5,特地下载下来确认,如下图,但是自己使用却只能使用2.0.4。
这里我们可以直接使用接口来推消息,与上一篇activemq用法类似。
由于spring没有主动提供配置rocketmq,我们只能按照rocketmq提供的springboot规范,这时我们打开rocketmq的配置可以看见它有自己的默认规范,比如group的参数:
我们在配置文件中也可以看到详细的参数配置:
故我们依据需要进行配置:
然后就是组件开发,我们需要封装自己需要的推送,例如我们可以实现template接口,或者直接注入依赖也可以:
然后就是在service中应用,直接注入使用即可:
至于可视化效果可以安装rocketmq-console插件来支持。
https://github.com/apache/rocketmq-externals/tree/master/rocketmq-console
下载后导入项目,配置:
更改配置和偶启动服务,然后可以看到rocketmq的操作页面:
可以查询自定义的主题:
推送结果:
rocketmq可视化工具功能比较齐全,部分功能可以通过监控客户端处理。
code源码:
https://github.com/lovezmming/zm-mq
微信公众号:像是风