rocketMQ 实战与原理解析读后感

《第一章:快速入门》

消息队列:基础数据结构里的先进先出的数据结构。

消息队列的作用:
1.应用解耦
2.流量削峰
3.消息分发
4.保证最终一致性,方便动态扩容等功能
5.日志记录
rocketmq优点
支持集群模型,负载均衡,水平扩展能力
亿级别的消息堆积能力
采用零拷贝的原理,顺序写盘,随机读
代码优秀,底层通信框架采用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 回车

访问:http://localhost:8080/

如果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:9876NamerServer 的地址可以是多个
brokerClusterName=DefaultClustercluster 的地址,如果集群机器比较多,可以分成多个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_FLUSHflushDiskType 表示刷盘策略:分别sync_flush & async_flush 两种,分别代表同步刷盘和异步刷。同步刷盘情况下,消息真正写入磁盘后再返回成功状态;异步刷盘情况下,消息写入page_cache 后就返回成功状态。
listenPort=10911broker 监听的端口号,如果一台机器上启动了多个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 。

mq消息发送&消费具体流程:
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 同时发送。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值