基础篇
MQ介绍
为什么要用MQ
- MQ(Message Queue)消息队列,是基础数据结构中“先进先出”的一种数据结构。
- 其应用场景主要包含以下几个方面:
异步解耦
- 以电商应用为例,应用中有订单系统、库存系统、物流系统、支付系统。用户创建订单后,如果耦合调用库存系统、物流系统、支付系统,任何一个子系统出了故障,都会造成下单操作异常。
- 当转变成基于消息队列的方式后,系统间调用的问题会减少很多,比如物流系统因为发生故障,需要几分钟来修复。在这几分钟的时间里,物流系统要处理的内存被缓存在消息队列中,用户的下单操作可以正常完成。当物流系统恢复后,继续处理订单信息即可,用户感受不到物流系统的故障。提升了系统的可用性。
削峰填谷
- 举个栗子,如果订单系统最多能处理一万次订单,这个处理能力应付正常时段的下单时绰绰有余,正常时段我们下单一秒后就能返回结果。但是在高峰期,如果有两万次下单操作系统是处理不了的,只能限制订单超过一万后不允许用户下单。
- 使用消息队列做缓冲,我们可以取消这个限制,把一秒内下的订单分散成一段时间来处理,这时有些用户可能在下单十几秒后才能收到下单成功的操作,但是比不能下单的体验要好。
数据分发
- 多个服务对数据感兴趣,只需要监听同一类消息即可处理。例如A产生数据,B对数据感兴趣。如果每个消息的队列A每次处理完需要调用一下B服务。过了一段时间C对数据也感兴趣,A就需要改代码,调用B服务,调用C服务。只要有服务需要,A服务都要改动代码。很不方便。有了消息队列后,A只管发送一次消息,B对消息感兴趣,只需要监听消息。C感兴趣,C也去监听消息。A服务作为基础服务完全不需要有改动。
异步消息
- 有些服务间调用是异步的,例如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服务还能及时的得到异步处理成功的消息。
其他
- 顺序收发:细数日常中需要保证顺序的应用场景非常多,比如证券交易过程时间优先原则,交易系统中的订单创建、支付、退款等流程,航班中的旅客登机消息处理等等。与先进先出(First In First Out,缩写 FIFO)原理类似,消息队列 MQ 提供的顺序消息即保证消息 FIFO。
- 分布式事务一致性:交易系统、支付红包等场景需要确保数据的最终一致性,大量引入消息队列 MQ 的分布式事务,既可以实现系统之间的解耦,又可以保证最终的数据一致性。
- 大数据分析:数据在“流动”中产生价值,传统数据分析大多是基于批量计算模型,而无法做到实时的数据分析,利用阿里云消息队列 MQ 与流式计算引擎相结合,可以很方便的实现将业务数据进行实时分析。
- 分布式缓存同步:天猫双 11 大促,各个分会场琳琅满目的商品需要实时感知价格变化,大量并发访问数据库导致会场⻚面响应时间⻓,集中式缓存因为带宽瓶颈限制商品变更的访问流量,通过消息队列 MQ 构建分布式缓存,实时通知商品数据的变化。
MQ的缺点
- 系统可用性降低:系统引入的外部依赖越多,系统稳定性越差,一旦MQ宕机,就会对业务造成影响。如何保证MQ的高可用?
- 系统的复杂度提高:MQ的加入大大增加了系统的复杂度,以前系统间是同步的远程调用,现在是通过MQ进行异步调用。如何保证消息没有被重复消费?怎么处理消息丢失情况?怎么保证消息传递的顺序性。
- 一致性问题:A系统处理完业务,通过MQ给B、C、D三个系统发消息数据,如果B、C处理成功,D处理失败。如何保证消息数据处理的一致性?
RocketMQ的前世今生
- RocketMQ是一款阿里巴巴开源的消息中间件,在2017年9月份成为Apache的顶级项目,是国内首个互联网中间件在 Apache 上的顶级项目。
- RocketMQ的起源受到另一款消息中间件Kafka的启发。最初,淘宝内部的交易系统使用了淘宝自主研发的Notify消息中间件,使用Mysql作为消息存储媒介,可完全水平扩容。为了进一步降低成本和提升写入性能,需要在存储部分可以进一步优化,2011年初,Linkin开源了Kafka这个优秀的消息中间件,淘宝中间件团队在对Kafka做过充分Review之后,被Kafka无限消息堆积,高效的持久化速度所吸引。
- 不过当时Kafka主要定位于日志传输,对于使用在淘宝交易、订单、充值等场景下还有诸多特性不满足,例如:延迟消息、消费重试、事务消息、消息过滤等,这些都是一些企业级消息中间件需要具备的功能。为此,淘宝中间件团队重新用Java语言编写了RocketMQ,定位于非日志的可靠消息传输。不过随着RocketMQ的演进,现在也支持了日志流式处理。
- 目前RocketMQ经过了阿里多年双十一大促的考验,性能和稳定性得到了充分的验证。目前在业界被广泛应用在订单,交易,充值,流计算,消息推送,日志流式处理,binlog分发等场景。
- RocketMQ整个产品发展历史主要经历以下几个阶段:
- 阶段1 Metaq(Metamorphosis) 1.x:由开源社区 killme2008 维护,开源社区地址:https://github.com/killme2008/Metamorphosis,最后一次更新是在2017年1月份。
- 阶段2 Metaq 2.x:于 2012 年 10 月份上线,在淘宝内部被广泛使用。
- 阶段3 RocketMQ 3.x:基于阿里内部开源共建原则, RocketMQ 项目只维护核心功能,且去除了所有其他运行时依赖,核心功能最简化。每个 BU 的个性化需求都在 RocketMQ 项目之上进行深度定制。 RocketMQ 向其他BU 提供的仅仅是Jar 包,例如要定制一个 Broker,那么只需要依赖 rocketmq-broker 这个 jar 包即可,可通过 API 进行交互,如果定制 client,则依赖 rocketmq-client 这个 jar 包,对其提供的 api 进行再封装。
- 阶段4 进入Apache:2016年11月28日,阿里巴巴向 Apache 软件基金会捐赠消息中间件 RocketMQ,成为 Apache 孵化项目。美国时间 2017 年 9 月 25 日,Apache 软件基金会(ASF)宣布 Apache®RocketMQTM 已孵化成为 Apache 顶级项目(TLP ),是国内首个互联网中间件在 Apache 上的顶级项目。官网地址:http://rocketmq.apache.org/
各种MQ产品的比较
- 目前业界还有很多其他MQ,如Kafka、RabbitMQ、ActiveMQ、Apache Pulsar等。下图列出了全球范围内这些MQ在2018.12~2019.12一年时间内,在Google Trends的搜索频率,某种程度可以反映出这些中间件的火爆程度。
- 从这张图上,我们可以看出来,Kafka是一枝独秀,RabbitMQ紧接其后,ActiveMQ和Apache Pulsar也有一定的占比。而RocketMQ的搜索量可以说是微乎其微。
- 对于除了RocketMQ的其他几个MQ产品,可以根据这张图初步对比下流行程度。但是对于RocketMQ必须排除在外,因为一些原因,很多国内的用户无法通过Google进行搜索,因此关于RocketMQ的统计实际上是不准确的。
- 而在这里,我们主要对比的是RocketMQ与其他MQ有哪些功能特性上的差异。功能特性,主要取决于产品定位,如Kafka定位于高吞吐的流失日志和实时计算场景;ActiveMQ、RabbitMQ等则定位于企业级消息中间件,因此提供了很多企业开发时非常有用的功能,如延迟消息、事务消息、消息重试、消息过滤等,而这些特性Kafka都不具备,但是这类产品的吞吐量要明显的低于Kafka。
- RocketMQ则是结合了Kafka和ActiveMQ、RabbitMQ的特性。在性能上,可以与Kafka抗衡;而在企业级MQ的特性上,则具备了很多ActiveMQ、RabbitMQ提供的特性。因此,企业在选择消息中间件选型时,RocketMQ是非常值得考虑的一款产品。
- 下图列出了RocketMQ与其他消息中间件的对比- :
特性 | ActiveMQ | RabbitMQ | RocketMQ | Kafka |
---|---|---|---|---|
开发语言 | java | erlang | java | scala |
单机吞吐量 | 万级 | 万级 | 十万级 | 十万级 |
Topic数量对吞吐量影响 | Topic可以达到几百、几千个的级别,吞吐量会有小幅度的下降。 | Topic从几十个到几百个的时候,吞吐量会大幅下降。 | ||
时效性 | 毫秒 | 微秒级 | 毫秒 | 毫秒 |
可用性 | 高,基于主从架构实现可用性 | 高,基于主从架构实现可用性 | 非常高,分布式架构 | 非常高,Kafka是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用 |
消息可靠性 | 有较低的概率丢失数据 | 经过参数优化配置,可以做到零丢失 | 经过参数优化配置,可以做到零丢失 | |
功能支持 | MQ领域的功能及其完备 | 基于erlang开发,所以并发性能极强,性能极好,延时低 | MQ功能较为完备,分布式扩展性好 | 功能较为简单,主要支持主要的MQ功能,像一些消息查询,消息回溯等功能没有提供,毕竟是为大数据准备的,在大数据领域应用广 |
优势 | 非常成熟,功能强大,在业内大量公司和项目中都有应用 | erlang语言开发,性能极好、延时很低,吞吐量万级、MQ功 能完备,管理界面非常好,社区活跃;互联网司使用较多 | 接口简单易用,阿里出品有保障,吞吐量大,分布式扩展方 便、社区比较活跃, 支持大规模的Topic、 支持复杂的业务场景,可以基于源码进行定制开发 | 超高吞吐量,ms级的时延,极高的可用性和可靠性,分布式扩展方便 |
劣势 | 偶尔有较低概率丢失消息,社区活跃度不高 | 吞吐量较低,erlang语音开发不容易进行定制开发,集群动态扩展麻烦 | 接口不是按照标准JMS规范走的,有的系统迁移要修改大量的代码,技术有被抛弃的 ⻛险 | 有可能进行消息的重复消费 |
应用 | 主要用于解耦和步,较少用在大规模吞吐的场景中 | 都有使用 | 用于大规模吞吐、复杂业务中 | 在大数据的实时计算和日志采集中被大规模使用,是业界的标准 |
总结
- 一般业务系统要引入 MQ,最早大家都用 ActiveMQ,但现在用的不多了。没有经过大规模吞吐场景的验证,社区也不活跃,不推荐再使用。后来大家开始用 RabbitMQ,但是它是使用 erlang 语言开发的,如果不精通 erlang,对公司而言,几乎处于不可控的状态,尤其是开源的,社区活跃度高,拥有比较稳定的支持。现在越来越多的公司开始使用 RocketMQ,但是要小心被抛弃的⻛险。如果公司有实力自己去维护开发,推荐使用,否则还是选择 RabbitMQ。如果实在大数据的实时计算、日志采集等领域,用 Kafka 是业界标准。
- 所以,对于中小型公司,技术实力一般的,应该用 RabbitMQ,对于大公司,基础架构研发能力强大的,推荐使用 RocketMQ。
快速入门-安装教程
- RocketMQ 是阿里巴巴在2012年开源的分布式消息中间件,目前已经捐赠给 Apache 软件基金会,并于2017年9月25日成为Apache 的顶级项目。作为经历过多次阿里巴巴双十一这种“超级工程”的洗礼并有稳定出色表现的国产中间件,以其高性能、低延时和高可靠等特性近年来已经也被越来越多的国内企业使用。其主要功能有:
- 灵活可扩展性
- 海量消息堆积能力
- 支持顺序消息
- 多种消息过滤方式
- 支持事务消息等常用功能
单机安装
下载
- 源码下载:可以查看或修改源码
wget https://mirror.bit.edu.cn/apache/rocketmq/4.7.1/rocketmq-all-4.7.1-source-release.zip
# 或者
wget https://mirror.bit.edu.cn/apache/rocketmq/4.7.1/rocketmq-all-4.7.1-source-release.zip
wget https://mirrors.bfsu.edu.cn/apache/rocketmq/4.7.1/rocketmq-all-4.7.1-source-release.zip
wget https://mirrors.tuna.tsinghua.edu.cn/apache/rocketmq/4.7.1/rocketmq-all-4.7.1-source-release.zip
- 二进制可执行文件下载:
# 下载
wget https://mirrors.tuna.tsinghua.edu.cn/apache/rocketmq/4.7.1/rocketmq-all-4.7.1-bin-release.zip
# 或者
wget https://mirror.bit.edu.cn/apache/rocketmq/4.7.1/rocketmq-all-4.7.1-bin-release.zip
wget https://mirrors.bfsu.edu.cn/apache/rocketmq/4.7.1/rocketmq-all-4.7.1-bin-release.zip
wget https://mirrors.tuna.tsinghua.edu.cn/apache/rocketmq/4.7.1/rocketmq-all-4.7.1-bin-release.zip
安装并启动
- 解压编译源码:
unzip rocketmq-all-4.7.1-source-release.zip
cd rocketmq-all-4.7.1/
mvn -Prelease-all -DskipTests clean install -U
cd distribution/target/rocketmq-4.7.1/rocketmq-4.7.1
- 或者解压二进制文件包安装并启动:
# 解压
unzip rocketmq-all-4.7.1-bin-release.zip
- 目录介绍:
- bin:启动脚本,包含shell脚本和CMD脚本
- conf:实时配置文件,包括broker配置文件,logback配置文件等
- lib:依赖jar包,包含Netty、commons-lang、FastJSON等
# 启动
cd rocketmq-all-4.7.1-bin-release/
bin/mqnamesrv
可能遇到的问题
问题1
Unrecognized VM option 'MetaspaceSize=128m'
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
- 错误原因:JDK版本不匹配,JDK必须是1.8以上。
- 解决方案: 重新安装软件,配置JDK,安装1.8。之后重新启动。
问题2
Java HotSpot(TM) 64-Bit Server VM warning: Using the DefNew young collector with the CMS collector is deprecated and will likely be removed in a future release
Java HotSpot(TM) 64-Bit Server VM warning: UseCMSCompactAtFullCollection is deprecated and will likely be removed in a future release.
Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00000006ec800000, 2147483648, 0) failed; error='Cannot allocate memory' (errno=12)
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 2147483648 bytes for committing reserved memory.
# An error report file with more information is saved as:
# /usr/apps/rocketmq-all-4.7.1-bin-release/hs_err_pid10180.log
- 错误原因:是因为内存不够,导致启动失败。RocketMQ的配置默认是生产环境的配置,设置的jvm的内存 大小值比较大,对于学习而言没有必要设置这么大,测试环境的内存往往都不是很大,所以需要调整默认值。
- 解决方案:找到runserver.sh和runbroker.sh,编辑
# runserver.sh
JAVA_OPT="${JAVA_OPT} -server -Xms256m -Xmx256m -Xmn128m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
# runbroker.sh
JAVA_OPT="${JAVA_OPT} -server -Xms256m -Xmx256m -Xmn128m"
启动namesrv
- 直接启动
./mqnamesrv
- 后台启动:
#如果不存在nohup,使用命令安装:yum install coreutils
#如果 which nohup在usr/bin/nohup目录下存在,只是没有配置环境变量,要进行配置
#nohub必须配置vi ~/.bash_profile文件,在环境变量PATH中加入/usr/bin
#source ~/.bash_profile
#nohup --v #查询nohup的版本
nohup ./mqnamesrv > /dev/null 2>&1 &
- 查看日志:
tail -f ~/logs/rocketmqlogs/namesrv.log
启动broker
- 修改配置文件broker.conf:修改服务器中broker的配置,添加服务器IP(公网)
# 新增一行
# 你的公网IP
brokerIP1=192.168.254.120:10911
- 前台启动:端口必须指定9876
./mqbroker -n 192.168.254.120:9876 autoCreateTopicEnable=true
- 后台启动:
# 重点是: -c conf/broker.conf
nohup bin/mqbroker -n 192.168.254.120:9876 autoCreateTopicEnable=true -c conf/broker.conf > /dev/null 2>&1 &
- 查看日志:
tail -f ~/logs/rocketmqlogs/broker.log
消息测试
- 配置nameserver地址:
# 编辑profile文件
vim /etc/profile
# 设置nameserver服务器
export NAMESRV_ADDR=192.168.254.120:9876
# 刷新
source /etc/profile
- 测试消息发送命令:
[root@centos100 bin]# sh tools.sh org.apache.rocketmq.example.quickstart.Producer
- 测试消息接收命令:
[root@centos100 bin]# sh tools.sh org.apache.rocketmq.example.quickstart.Consumer
关闭RocketMQ
> sh bin/mqshutdown broker
The mqbroker(53398) is running...
Send shutdown request to mqbroker(53398) OK
sh bin/mqshutdown namesrv
The mqnamesrv(53194) is running...
Send shutdown request to mqnamesrv(53194) OK
[2]+ 退出 143 nohup ./mqbroker -n 192.168.254.120:9876 autoCreateTopicEnable=true > /dev/null 2>&1(工作目录:/usr/apps/rocketmq-all-4.7.1-bin-release/bin)
(当前工作目录:/usr/apps/rocketmq-all-4.7.1-bin-release)
管理工具
mqadmin管理工具
- 更新和修改RocketMQ属性和部署属性的方式有两个,一个是使用控制台图形化界面来修改,另一个是使用mqadmin工具通过命令来修改,这里就说说mqadmin的使用方式。
- 进入ROCKETMQ_HOME/bin,在该目录下有个mqadmin 脚本
[root@centos120 bin]# pwd
/usr/apps/rocketmq-all-4.7.1-bin-release/bin
[root@centos120 bin]# ll mqadmin
-rwxr-xr-x. 1 root root 1400 6月 24 14:02 mqadmin
rocketmq-console
- 管理查看RocketMQ最好的办法是通过图形化界面。RocketMQ的源码并没有提供对应的图形化管理工具,但是我们可以使用RocketMQ-Console这个图形化工具。
- githup地址:https://github.com/apache/rocketmq-externals
- 中文手册:https://github.com/apache/rocketmq-externals/blob/master/rocketmq-console/doc/1_0_0/UserGuide_CN.md
下载解压
# 下载
wget https://github.com/apache/rocketmq-externals/archive/rocketmq-console-1.0.0.zip
# 解压
unzip rocketmq-console-1.0.0.zip
cd rocketmq-externals-rocketmq-console-1.0.0/rocketmq-console
修改部分参数并编译
- rocketmq-console默认情况下是免登陆的,为了安全起⻅我们设置用户名密码登录,修改 src目录下的 application.properties 文件。
vim src/main/resources/application.properties
# 这个填写自己的nameserver的地址,默认是localhost:9876
rocketmq.config.namesrvAddr=192.168.254.120:9876
# rocketmq-console的数据目录,默认为 /tmp/rocketmq-console/data
rocketmq.config.dataPath=/usr/local/rocketmq-console/data
# 修改为false,否则访问时会报错【org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to <172.17.0.1:10909> failed】,默认true
rocketmq.config.isVIPChannel=fasle
# 是否开启认证登录功能,默认为false
rocketmq.config.loginRequired=false
- 修改了以上参数之后,使用maven进行编译:
mvn clean package -Dmaven.test.skip=true
- 可能会报错:
- 解决办法:删掉maven-checkstyle-plugin插件。
运行编译后的jar包
nohup java -jar target/rocketmq-console-ng-1.0.0.jar &
打开浏览器验证
- 访问地址:http://192.168.254.130:8080
- dashboard
- cluster:
- topic:
开启登录验证
vim src/main/resources/application.properties
# 开启认证登录功能,默认为false
rocketmq.config.loginRequired=true
- 在 rocketmq-console的数据目录下新建账户文件 users.properties 。
vim /usr/local/rocketmq-console/data/users.properties
# 该文件支持热修改,即添加和修改用户时,不需要重新启动console
# 格式:每行定义一个用户,username=password[,N]
# N是可选项,可以为0 (普通用户); 1 (管理员)
# 定义管理员
admin=123456,1
# 定义普通用户
#user1=user1
#user2=user2
集群搭建
集群搭建方式
单个Maste
- 优点:除了配置简单没什么优点,适合个⼈学习使⽤。
- 缺点:不可靠,该机器重启或宕机,将导致整个服务不可⽤。
多Master模式
- 多个 master 节点组成集群,单个 master 节点宕机或者重启对应⽤没有影响。
- 优点:所有模式中性能最⾼。
- 缺点:单个 master 节点宕机期间,未被消费的消息在节点恢复之前不可⽤,消息的实时性就受到影响。
- 注意:使⽤同步刷盘可以保证消息不丢失,同时 Topic 相对应的 queue 应该分布在集群中各个节点,⽽不是只在某各节点上,否则,该节点宕机会对订阅该 topic 的应⽤造成影响。
多Master多Slave模式,异步复制
- 在多 master 模式的基础上,每个 master 节点都有⾄少⼀个对应的 slave。master 节点可读可写,但是 slave 只能读不能写,类似于 mysql 的主备模式。
- 优点:性能最好,在 master 宕机时,消费者可以从 slave读取消息,消息的实时性不会受影响,性能⼏乎和多 master ⼀样。
- 缺点:使⽤异步复制的同步⽅式有可能会有消息丢失的问题。
多Master多Slave模式,同步双写
- 同多 master 多 slave 异步复制模式类似,区别在于 master 和 slave 之间的数据同步⽅式。
- 优点:同步双写的同步模式能保证数据不丢失。
- 缺点:⽐异步复制的性能差10%。
RocketMQ提供的集群模式
- 刷盘策略:同步刷盘和异步刷盘(指的是节点⾃身数据是同步还是异步存储)。
- 同步⽅式:同步双写和异步复制(指的⼀组 master 和 slave 之间数据的同步)。
注意:要保证数据可靠,需采⽤同步刷盘和同步双写的⽅式,但性能会较其他⽅式低。
- Master和Slave的配置⽂件参考conf⽬录下的配置⽂件。
- Master与Slave通过指定相同的brokerName参数来配对,Master的BrokerId必须是0,Slave的BrokerId必须是⼤于0的数。
- ⼀个Master下⾯可以挂载多个Slave,同⼀Master下的多个Slave通过指定不同的BrokerId来区分。
- Rocketmq默认给出了三种建议配置模式:2m-2s-async(主从异步)、2m-2s-sync(主从同步)、2mnoslave(仅master)。
双主双从集群搭建
- 上图为双主双从集群原理图,其中Name Server是⼀个⼏乎⽆状态节点,可集群部署,节点之间⽆任何信息同步。
- Broker分为Master与Slave,⼀个Master可以对应多个Slave,但是⼀个Slave只能对应⼀个Master,Master与Slave的对应关系通过指定相同的Broker Name,不同的Broker Id来定义,BrokerId为0表示Master,⾮0表示Slave。双主双从集群中有两个Master,每个Master对应⼀个Slave。
- 每个Broker与Name Server集群中的所有节点建⽴⻓连接,定时(每隔30s)注册Topic信息到所有Name Server。Name Server定时(每隔10s)扫描所有存活Broker的连接,如果Name Server超过2分钟没有收到⼼跳,则Name Server断开与Broker的链接。
- Producer与Name Server集群中的其中⼀个节点(随机选择)建⽴⻓连接,定期从Name Server取Topic路由信息,并向提供Topic服务的Master建⽴⻓连接,且定时向Master发送⼼跳。Producer完全⽆状态,可集群部署。
- Producer每隔30s(由ClientConfig的pollNameServerInterval)从Name server获取所有topic队列的最新情况,这意味着如果Broker不可⽤,Producer最多30s能够感知,在此期间内发往Broker的所有消息都会失败。
- Producer每隔30s(由ClientConfig中heartbeatBrokerInterval决定)向所有关联的Broker发送⼼跳,Broker每隔10s中扫描所有存活的连接,如果Broker在2分钟内没有收到⼼跳数据,则关闭与Producer的连接。
- Consumer与Name Server集群中的其中⼀个节点(随机选择)建⽴⻓连接,定期从Name Server取Topic路由信息,并向提供Topic服务的Master、Slave建⽴⻓连接,且定时向Master、Slave发送⼼跳。Consumer既可以从Master订阅消息,也可以从Slave订阅消息,订阅规则由Broker配置决定。
- Consumer每隔30s从Name server获取topic的最新队列情况,这意味着Broker不可⽤时,Consumer最多最需要30s才能感知。
- Consumer每隔30s(由ClientConfig中heartbeatBrokerInterval决定)向所有关联的Broker发送⼼跳,Broker每隔10s扫描所有存活的连接,若某个连接2分钟内没有发送⼼跳数据,则关闭连接,并向该Consumer Group的所有Consumer发出通知,Group内的Consumer重新分配队列,然后继续消费。
- 当Consumer得到Master宕机通知后,转向Slave消费,Slave不能保证Master的消息100%都同步过来了,因此会有少量的消息丢失。但是⼀旦Master恢复,未同步过去的消息会被最终消费掉。
集群工作流程
- 1、启动NameServer,NameServer起来后监听端⼝,等待Broker、Producer、Consumer连上来,相当于⼀个路由控制中⼼。
- 2、Broker启动,跟所有的NameServer保持⻓连接,定时发送⼼跳包,⼼跳包中包含当前Broker信息以及存储所有Topic信息,注册成功后,NameServer集群中就有Topic跟Broker的映射关系。
- 3、收发消息前,先创建Topic,创建Topic需要指定该Topic要存储在哪些Broker上,也可以在发送消息时⾃动创建Topic。
- 4、Producer发送消息,启动时先跟NameServer集群中的其中⼀台建⽴⻓连接,并从NameServer中获取当前发送的Topic存在哪些 Broker上,轮询从队列列表中选择⼀个队列,然后跟队列所在的Broker建⽴⻓连接从⽽向Broker发消息。
- 5、Consumer跟Producer类似,跟其中⼀台NameServer建⽴⻓连接,获取当前订阅Topic存在哪些Broker上,然后直接跟Broker家⾥连接通道,开始消费消息。
2m-2s-sync集群搭建
- 修改配置文件:
${RocketMQ_HOME}/conf/2m-2s-sync/broker-a.properties
${RocketMQ_HOME}/conf/2m-2s-sync/broker-a-s.properties
${RocketMQ_HOME}/conf/2m-2s-sync/broker-b.properties
${RocketMQ_HOME}/conf/2m-2s-sync/broker-b-s.properties
- 例如broker-a.properties、broker-a-s.properties的配置如下:
# broker-a.properties
# 监听端口
listenPort=10911
# 集群名称
brokerClusterName=rmq-cluster
# broker名称
brokerName=broker-a
# 0:master, 1:slave
brokerId=0
deleteWhen=04
fileReservedTime=48
brokerRole=SYNC_MASTER
flushDiskType=ASYNC_FLUSH
# 存储路径,需要先创建目录
storePathRootDir=/usr/local/rocketmq/store-a/
storePathCommitLog=/usr/local/rocketmq/store-a/commitlog/
storePathConsumerQueue=/usr/local/rocketmq/store-a/consumequeue/
# broker-a-s.properties
# 监听端口
listenPort=10921
# 集群名称
brokerClusterName=rmq-cluster
# broker名称
brokerName=broker-a
# 0:master, 1:slave
brokerId=1
deleteWhen=04
fileReservedTime=48
brokerRole=SALVE
flushDiskType=ASYNC_FLUSH
# 存储路径
storePathRootDir=/usr/local/rocketmq/store-a-s/
storePathCommitLog=/usr/local/rocketmq/store-a-s/commitlog/
storePathConsumerQueue=/usr/local/rocketmq/store-a-s/consumequeue/
- broker-b.properties和broker-b-s.properties的配置类似:
# broker-b.properties
# 监听端口
listenPort=10931
# 集群名称
brokerClusterName=rmq-cluster
# broker名称
brokerName=broker-b
# 0:master, 1:slave
brokerId=0
deleteWhen=04
fileReservedTime=48
brokerRole=SYNC_MASTER
flushDiskType=ASYNC_FLUSH
# 存储路径,先创建目录
storePathRootDir=/usr/local/rocketmq/store-b/
storePathCommitLog=/usr/local/rocketmq/store-b/commitlog/
storePathConsumerQueue=/usr/local/rocketmq/store-b/consumequeue/
# broker-b-s.properties
# 监听端口
listenPort=10941
# 集群名称
brokerClusterName=rmq-cluster
# broker名称
brokerName=broker-b
# 0:master, 1:slave
brokerId=1
deleteWhen=04
fileReservedTime=48
brokerRole=SALVE
flushDiskType=ASYNC_FLUSH
# 存储路径
storePathRootDir=/usr/local/rocketmq/store-b-s/
storePathCommitLog=/usr/local/rocketmq/store-b-s/commitlog/
storePathConsumerQueue=/usr/local/rocketmq/store-b-s/consumequeue/
- 启动
nohup bin/mqbroker -n 192.168.254.130:9876 -c conf/2m-2s-sync/broker-a.properties > /dev/null 2>&1 &
nohup bin/mqbroker -n 192.168.254.130:9876 -c conf/2m-2s-sync/broker-a-s.properties > /dev/null 2>&1 &
nohup bin/mqbroker -n 192.168.254.130:9876 -c conf/2m-2s-sync/broker-b.properties > /dev/null 2>&1 &
nohup bin/mqbroker -n 192.168.254.130:9876 -c conf/2m-2s-sync/broker-b-s.properties > /dev/null 2>&1 &
- 验证
bin/mqadmin clusterlist