《第一章:快速入门》
消息队列:基础数据结构里的先进先出的数据结构。
1.应用解耦 |
2.流量削峰 |
3.消息分发 |
4.保证最终一致性,方便动态扩容等功能 |
5.日志记录 |
支持集群模型,负载均衡,水平扩展能力 |
亿级别的消息堆积能力 |
采用零拷贝的原理,顺序写盘,随机读 |
代码优秀,底层通信框架采用netty nio 框架 |
nameserver 代替zookeper [更轻量级] |
消息失败重试机制,消息可查询 |
broker 负责失败消息重新发送 |
开源社区活跃,成熟度(经过双十一考验) |
consumer group: | 消费者集合,一般用于接收一类消息producer group: 生产者集合,一般用于发送一类消息 |
broker: | mq 消息服务(中转角色,用于消息存储与生产消费转发) |
rocketmq-broker: | 主要的业务逻辑,消息收发,主从同步,pagecache。 |
rocketmq-client: | 客户端接口,比如生产者和消费者 |
rocketmq-example: | 示例,比如生产者和消费者 |
rocketmq-common: | 公用数据结构等 |
rocketmq-distribution: | 编译模块,编译输出等 |
rocketmq-filter: | 进行broker过滤的不感兴趣的消息传输,减小带宽压力 |
rocketmq-logappender,rocketmq-logging: | 日志相关 |
rocketmq-namesrv : | 用于服务协调 |
rocketmq-open messaging: | 对外提供服务 |
rocketmq-remoting : | 远程调用接口,封装netty底层通信。 |
rocketmq-srvutil: | 提供一些公用的工具方法,比如解析命令行参数 |
rocketmq-store: | 消息存储 |
rocketmq-tools: | 管理工具,比如mqadmin 工具。 |
rocketMq安装: Downloading the Apache RocketMQ Releases - Apache RocketMQ
1.rocketmq下载地址:https://www.apache.org/dyn/closer.cgi?path=rocketmq/4.7.0/rocketmq-all-4.7.0-bin-release.zip
2.配置环境变量:变量名:ROCKETMQ_HOME 变量值:C:\tools\rocketmq\rocketmq-all-4.7.0-bin-release
3.启动NameServer
cmd ---》cd C:\tools\rocketmq\rocketmq-all-4.7.0-bin-release\bin ---》start mqnamesrv.cmd ---》回车,显示下方即成功哦
4.启动broker:cmd ---》cd C:\tools\rocketmq\rocketmq-all-4.7.0-bin-release\bin ---》 start mqbroker.cmd autoCreateTopicEnable=true +回车。[如果不能选择集群,则用下面两个启动,两个都要运行哦]
4.启动:start mqbroker.cmd -c ../conf/2m-2s-async/broker-a.properties
4.启动: start mqbroker.cmd -c ../conf/2m-2s-async/broker-a-s.properties
注意如果不能启动,则删除C:\Users\你的用户名\store 中的所有内容,显示下方则成功
benchmark 里包括运行 benchmark 程序的 shell 脚本;
bin 文件夹里含有各种使RocketMQ shell 脚本( Linux 平台)和 cmd 脚本( Windows 平台),比如常用的启动 NameServer 的脚 mqnamesrv ,启动 Broker 的脚本 mqbroker群管理脚本 mqadmin
conf 件夹里有 些示例配置文件,包括 种方式的broker 文件、 logback 文件等,用户在 文件的时候,一般基于这些示例配置文件,加上 己特殊的 求即可;
lib 夹里包括 RocketMQ各个模块编译成的 jar 包,以及 RocketMQ 依赖的 jar 包,比如 Netty commons lang FastJSON
关闭消息队列:消息队列被启动后,如果不主动关闭,则会一直在后台运行,占用系统资源。
linux 下载安装并启动:
1安装: | unzip rocketmq-all-4.2.0-bin-release.zip -d ./rocketmq-all-4.2.0-bin ls |
2.查看: | cd rocketmq-all-4.2.0-bin/ |
3.启动NameServer: | nohup sh bin/mqnamesrv & |
3~1.查看启动log: | tail -f ~/Logs/rocketmqLogs/namesrv.Log |
4.启动broker: | nohup sh bin/mqbroker -n localhost:9876& |
4~1.查看启动log: | tail -f ~/Logs/rocketmqLogs/broker.Logs |
5.关闭Broker: | sh bin/mqshutdown broker |
6.关闭NameServer: | sh bin/mqshutdown namesrv |
rocketmq-console下载地址:
https://github.com/apache/rocketmq-externals/tree/master/rocketmq-console
借助图形工具查看rocketmq 消息
下载地址:https://github.com/apache/rocketmq-externals/tree/master/rocketmq-console/
修改rocketmq-console:application.properties :rocketmq.config.namesrvAddr=127.0.0.1:9876
启动方式1 idea 输入命令 :spring-boot:run
启动方式2 进入D:\tools\rocket-console\rocketmq-externals\rocketmq-console---》按住Shift +右键 打开命令行,
输入命令:mvn clean package -Dmaven.test.skip=true,
此时,D:\tools\rocket-console\rocketmq-externals\rocketmq-console\target 会生成jar 包,
然后命令启动:cmd --->cd D:\tools\rocket-console\rocketmq-externals\rocketmq-console\target
java -jar rocketmq-console-ng-1.0.1.jar 回车
如果broker 无法启动,不显示下方的图,则删除:C:\Users\luoxian\store 包
当然也可以下载我编译好的jar 包运行:rocketmq-console-ng-1.0.1.jar_rocketmq-console-ng-1.0.1.jar-WindowsServer文档类资源-CSDN下载
cd C:\tools\rocketmq\rocketmq-4.7.0-console --->java -jar rocketmq-console-ng-1.0.1.jar
配置集群:关于rocketMq的windows集群部署工作日志 - it610.com
写个发送消息的实例:
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.7.0</version>
</dependency>
public static void main(String[] args) {
DefaultMQProducer producer = new DefaultMQProducer("group_word");
producer.setNamesrvAddr("192.168.99.1:9876");
producer.setSendMsgTimeout(60000);
producer.setVipChannelEnabled(false);
try {
producer.start();
for (int i = 0 ;i<5;i++) {
Message message = new Message("topic_word","tag_word",i+"_key",100,
("hello_word"+i).getBytes(RemotingHelper.DEFAULT_CHARSET),true);
SendResult sendResult = producer.send(message);
System.out.println("发送rocketMQ的结果:{}"+sendResult.getSendStatus());
}
} catch (Exception e) {
e.printStackTrace();
}
producer.shutdown();
}
《第二章:生产环境下的配置和使用》
rocketMQ各部分角色组成:producer,consumer,broker,nameServer
启动rocketmq 的顺序是先启动nameServer,再启动Broker,这时候消息队列已经可以提供服务了,使用producer 发送消息,使用consumer接收消息。应用程序既要发送又要接收,可以启动多个producer & consumer来发送多种消息,同时接受多种消息。
总结: | 为了消除单点故障,增加可靠性或增大吞吐量,可以在多台机器上部署多个nameServer & Broker。为每个Broker 部署一个或多个Slave。 |
Topic: | 同一个业务不同类型的消息投递,这些不同类型的消息以不同的topic 名称来区分。 |
Message Queue: | 如果一个topic 要发送和接受的数据量非常大,需要能增加并行处理的机器来提高处理速度,这时候一个topic 可以根据需求设置一个或多个Message queue。 message queue 类似分区或parttion。topic 有了多个message queue 后,消息可以并行的向各个message queue 发送,消费者也可以并行的从多个message queue 读取消息并消费。 |
多机集群配置和部署:
1.首先在两台机器上分别启动NameServer: nohup sh bin/mqnameserv &
此时我们得到了两个NameServer,服务地址: 192.168.100.131:9876; 192.168.100.132:9876;
2.然后启动Broker ,每台机器上都要分别启动一个Master 角色的Broker 和一个Slave 角色的Broker ,并互为主备。
192.168.100.131 机器上的Master Broker 的配置文件:
namesrvAddr=192.168.100.131:9876;192.168.100.132:9876
brokerClusterName=DefaultCluster
brokerName=broker-a
brokerId=0
deleteWhen=04
fileReservedTime=48
brokerRole=SYNC_MASTER
flushDiskType=ASYNC_FLUSH
listenPort=10911
storePathRootDir=/home/rocketmq/store-a
192.168.100.132 机器上的Master Broker 的配置文件:
namesrvAddr=192.168.100.131:9876;192.168.100.132:9876
brokerClusterName=DefaultCluster
brokerName=broker-b
brokerId=0
deleteWhen=04
fileReservedTime=48
brokerRole=SYNC_MASTER
flushDiskType=ASYNC_FLUSH
listenPort=10911
storePathRootDir=/home/rocketmq/store-b
192.168.100.131 机器上的Slave Broker 的配置文件:
namesrvAddr=192.168.100.131:9876;192.168.100.132:9876
brokerClusterName=DefaultCluster
brokerName=broker-b
brokerId=1
deleteWhen=04
fileReservedTime=48
brokerRole=SLAVE
flushDiskType=ASYNC_FLUSH
listenPort=11011
storePathRootDir=/home/rocketmq/store-b
192.168.100.132 机器上的Slave Broker 的配置文件:
namesrvAddr=192.168.100.131:9876;192.168.100.132:9876
brokerClusterName=DefaultCluster
brokerName=broker-a
brokerId=1
deleteWhen=04
fileReservedTime=48
brokerRole=SLAVE
flushDiskType=ASYNC_FLUSH
listenPort=11011
storePathRootDir=/home/rocketmq/store-a
分别使用命令启动四个broker:
nohup sh ./bin/mqbroker -c config_file &
此时一个高可用的rocketMQ 集群就搭建好了。可以在一台机器上启动rocketmq-console ,然后在浏览器上访问:192.168.100.131:8080
namesrvAddr=192.168.100.131:9876;192.168.100.132:9876 | NamerServer 的地址可以是多个 |
brokerClusterName=DefaultCluster | cluster 的地址,如果集群机器比较多,可以分成多个cluster,每个cluster 供一个业务群使用 |
brokerName=broker-a | Broker的名称,master & slave 通过使用相同的broker 名称来表名相互关系 |
brokerId=0 | 一个Master Broker 可以有多个slave ,0表示Master,大于0 表示不同的slave 的ID |
fileReservedTime=48 | 在磁盘上保存的时长,单位是小时,自动删除超时的消息 |
deleteWhen=04 | 与fileReservedTime 参数呼应,表示在几点做删除动作,默认值04表示凌晨四点执行删除 |
brokerRole=SLAVE | brokerRole 有3种: sync_master, async_master, slave 。 关键词sync 和 async 表示master 和 slave 之间同步消息的机制。sync 表示当slave 和主库消息同步完成后,再返回发送发送成功的状态。 |
flushDiskType=ASYNC_FLUSH | flushDiskType 表示刷盘策略:分别sync_flush & async_flush 两种,分别代表同步刷盘和异步刷盘。同步刷盘情况下,消息真正写入磁盘后再返回成功状态;异步刷盘情况下,消息写入page_cache 后就返回成功状态。 |
listenPort=10911 | broker 监听的端口号,如果一台机器上启动了多个broker,则要设置不同的端口号,避免冲突。 |
storePathRootDir=/home/rocketmq/store-a | 存储消息以及一些配置信息的根目录 |
注意:配置参数变化,broker需要重启
mqAdmin 是rocketMQ 自带的管理工具,在bin 目录下,运行mqadmin 即可,可以进行创建和修改topic,更新broker 的配置信息等。
《第三章:用适合的方式发送和接收消息》
不同类型的消费者:根据使用者对读取操作的控制情况,消费者分为两种类型。
push: | 一个是defaultMQPushConsumer,由系统控制读取操作。收到消息后自动调用传入的处理方法来处理。 |
pull: | 另一个是defaultMQPullConsumer 读取操作中的大部分功能由使用者自动控制。 |
rocketMQ 支持两种消息模式:clustering 和 broadcasting。
clustering 模式: | 同一个consumerGroup(groupName)里的每个Consumer 只消费订阅消息的一部分内容,同一个consumerGroup 里所有的Consumer 消费的内容合起来才是所订阅topic 内容的整体,从而达到负载均衡的目的。 |
broadcasting 模式: | 同一个ConsumerGroup 里的每个Consumer 都能消费到所订阅topic 的全部消息,也就是一个消息会被多次分发,被多个consumer 消费。 |
NameServer的地址和端口号可以填写多个,用分号隔开,达到消除单点故障的目的。
消费方式 | 优点 | 缺点 |
push方式 | server端接收到消息后,主动把消息推送给client端,实时性高。 | 增大server端的工作量,影响server性能。消费端的处理能力各不相同,可能会产生各种问题。 |
pull 方式 | pull方式是client 端循环的从server 端拉取消息,主动权在client。自己拉取到一定量消息后,处理妥当了再接收。 | 拉取间隔不好确定。 |
写入策略: 同步发送,异步发送,延迟发送,发送事务消息等。
生产者发送消息默认使用的是DefaultMQProducer。
发送一条消息要简要回答经过三个步骤:
1.客户端发送请求到服务器 |
2.服务器处理该请求 |
3.服务器向客户端返回应答 |
rocketMQ 发送消息详细的5大步骤:
1.设置producer 的groupName |
2.设置InstanceName,当一个jvm 需要启动多个producer 的时候,通过设置不同的instanceName 来区分,不设置的话系统使用默认名称:default。 |
3.设置发送失败重试次数,当网络出现异常的时候,这个次数影响消息的重复投递次数,想保证不丢消息,可以设置多重试几次。 |
4.设置NameServer 地址。 |
5.组装消息并发送。 |
消息发送的返回状态有4个flush_disk_timeout,flush_slave_timeout,slave_not_available,send_ok。
flush_disk_timeout: | 表示没有在规定时间内完成刷盘 |
flush_slave_timeout: | 表示在主备方式下,并且broker被设置成sync_master,没有在规定时间内完成主从同步。 |
slave_not_available: | 表示主从场景下,broker被设置成sync_master,但是没有找到被设置成slave 的broker。 |
send_ok: | 消息发送成功。 |
发送延迟消息:支持发送延迟消息,但是rockeMQ 有预定值,setDelayTimeLevel。
事务:
事务示例:A银行的某账户要转一万元给B银行的某账户。A银行发送[B银行账户增加一万元]这个消息,要从[A银行账户扣除一万元]这个操作同事成功或者同时失败。
对事务的支持:rocketMQ 采用两阶段提交的方式实现事务消息,先发一个[准备B银行账户增加一万元]的消息,发送成功后再从A银行账户扣除一万元的操作,根据操作结果是否成功,确定之前的消息做commit 还是rollback 。
1.发送方向Rocketqmq 发送待确认消息 |
2.rocketMq 将收到的待确认的消息持久化成功后,向发送方回复消息已经发送成功,此时第一阶段消息发送完成。 |
3.发送方开始执行本地事件逻辑 |
4.发送方根据本地事件执行结果向rocketMQ 发送二次确认commit/rollback 消息,rocketmq 收到commit 状态则将第一阶段消息标记为可投递,订阅方将能够收到该消息;收到rollback 状态则删除第一阶段的消息,订阅方接收不到该消息。 |
5.如果出现异常,步骤4提交的二次确认最终未到达rocketMq ,服务器在经过固定时间段后将对[待确认]消息发送回查请求。 |
6.发送方收到消息回查请求后,通过检查对应消息的本地事件执行结果返回commit 或rollback 状态。 |
7.rocketMQ 收到回查请求后,按照步骤4的逻辑处理。 |
客户端有三个类来支持用户实现事务消息,第一个类是LocalTransactionExecute,第二个类TransactionMQProducer,第三个类是TransactionCheckListener。
实际运行这种,重复消费某条消息,或者跳过一段时间内的消息,这个和offset 有关。
rocketMQ中,同种类型的消息会放到一个topic里,为了能够并行,一般一个topic会有多个message queue,offset 是指某个topic下的一条消息在某个Message Queue 里的位置,通过offset 的值可以定位到这条消息,或者指示consumer从这条消息开始向后继续处理。
自定义日志输出:
Log是监控系统状态,排查问题的手段。rocketMQ 的默认log 存储位置:${user.home}/Logs/rocketmqLogs,Log 配置文件的设置可以通过JVM 启动参数,环境变量,代码中的设置语句这三种方式设置的。
rocketmq 的log实现是基于slf4j 的,支持logback,log4j。
《第四章:分布式消息队列的协调者》
NameServer 维护消息队列的ip,连接信息等。NameServer 是整个消息队列中的状态服务器,集群的各个组件通过它了解全局的消息。同时,各个角色的机器都要定期向NameServer 报告自己的状态,超时不报,NameServer 会认为某个机器故障,其他组件将该机器移除。
协调消息组件用NameServer ,而不是ZooKeeper,就是因为它不需要进行选举,用不到那么复杂的功能。
《第五章:消息队列的核心机制》
broker 是rocketmq的核心,接收producer发过来的消息,处理consumer 的消费消息请求,消息的持久化存储,消息的Ha机制以及服务端过滤功能等。
消息存储结构:rocketmq消息存储是由consumeQueue 和 commitLog 配合完成的,消息真正的物理存储文件是CommitLog,ConsumeQueue是消息的逻辑队列,类似数据库的索引文件,存储的是指向物理存储的地址。每个topic 下的每个Message queue 都有一个对应的consumeQueue 文件,文件地址在
${$storeRoot}\consumequeue\${topicName}\${queueId}\${fileName}。每台broker上的commitLog 被本机器所有consumeQueue 共享。commitLog 中顺序写,随机读。
存储机制[顺序写,随机读]的优点:
1.commitLog 顺序写,可以大大提高写入效率。 |
2.虽然随机读,但还利用操作系统的pagecache 机制,可以批量的从磁盘读取,作为cache 存到内存中,加速后续的读取速度。 |
3.为了保证完全的顺序写,需要consumeQueue 这个中间结构组件。 注意:commitLog 里存储了consumeQueue ,message key,tag 等所有的信息,所以万一发生故障,可以通过commitLog 完全恢复过来。 |
部分顺序消息:要保证部分消息有序,需要生产者和消费者配合处理
1.生产者把同一业务ID的消息发送到同一个Message Queue; |
2.消费者从同一个message Queue 读取的消息不被并发处理。 |
消息重复问题:消息重复一般情况下不会发生,但是如果消息量大,网络有波动,消息重复就是个大概率事件。setRetryTimesWhenSendFailed 设置同步方式的自动重试次数,默认为2。
解决消息重复有两种方法[都是通过消费者实践]:
1.保证消费逻辑的幂等性 |
2.维护一个已消费消息的记录,消费前查询这个消息是否消费过。 |
《第六章:可靠性优先使用场景》
4种动态增减机器:一个消息队列集群由多台机器组成,持续稳定的提供服务,因为业务需求或硬件故障,经常需要增加或减少各个角色的机器。
1.动态增减nameServer
1.动态增减nameServer:nameServer 是rocketmq 集群的协调者,集群的各个组件是通过nameServer 获取各种属性和地址信息的。
nameServer功能:
1.各个broker定期上报自己的状态给nameServer;
2.各个客户端,包括生产者和消费者,以及命令行工具,通过nameServer 获取最新的状态消息。
注意: 为了提高可靠性,建议启动多个nameServer。
动态增减nameServer有4种的方法:
1.通过代码控制: producer.setNamesrvAddr("192.168.99.1:9876"); |
2.使用java 启动参数设置,对应的是option 是rocketmq.namesrv.addr |
3.通过Linux 环境变量设置,在启动前设置变量:NAMESRV_ADDR |
4.通过http 服务设置 |
2.动态增减broker :当需要对集群进行扩容的时候,可以动态增加broker 角色机器,只增加broker 不会对原有的topic产生影响,原来创建好的topic 中的数据的读写还在原来的那些broker上进行。
注释:集群扩容后,
1.可以把新建的topic指定到新的broker机器上,实现负载均衡;
2.可以通过updateTopic 来实现。
2-2动态减少broker 对数据的影响:是否有影响跟发送消息的方式有关。
1.如果同步方式发送消息,在defaultMQpRroducer 内部有个自动重试逻辑,其中一个broker停了,会自动的向另一个broker发送消息,所以不会发生丢失消息现象。
2.如果异步方式发送消息{callback},或者sendOneWay,会丢失切换过程中的消息。因为此时producer.setRetryTimesWhenSendFailed 设置不起作用,发送失败不会重试。
《第七章:吞吐量优先的使用场景》
1.在broker 端进行消息过滤:在broker端进行消息过滤,可以减少无效消息发送到consumer ,少占用网络带宽从而提高吞吐量。
broker端有三种方式进行消息过滤:
1.对一个应用来说,尽可能只使用一个topic,不同的消息子类型用tag 标识,服务器端基于tag 进行过滤,不需要读取消息体的内容,所以效率高。 |
2.通过tag 进行过滤。 |
3.用sql表达式的方式进行过滤。 |
4.filter server 方式过滤,filter server 是一种比sql表达式更灵活的过滤方式,允许用户自定义java函数,根据java函数的逻辑对消息进行过滤。 |
提高consumer 处理能力:
1.提高消息并行度: | 在同一个consumerGroup 下,可以通过增加consumer 实例的数量来提高并行度,但是数量不要超过topic 下read queue数量,超过的consumer 实例接收不到消息。此外通过单个consumer实例中的并行度来提高吞吐量[修改 consumeThreadMin & consumeThreadMax] |
2.批量消费: | 以批量方式进行消费[修改consumer的consumeMessageBatchMaxSize,默认为1,如果设置N,在消息多的时候每次收到的是个长度为N的消息链表] |
3.检测延时 | 检测延时情况,跳过非重要消息。 |
4.提高producer的并发量 | 提高producer的并发量,使用多个producer 同时发送。 |