apache-rocketmq 学习笔记

apache-rocketmq 学习笔记

环境准备

  • 本文使用的机器为 centos7
  • maven 版本为 3.6.1
  • jdk 版本 1.8.0_11

RocketMq 概念解读

  • Producer:消息生产者
  • Producer Group:消息生产者组,发送同类消息的一个消息生产组
  • Consumer:消费者
  • Consumer Group:消费同类消息的多个实例
  • Tag:标签,子主题(二级分类)对topic的进一步细化,用于区分同一个主题下的不同业务的消息
  • Topic:主题, 如订单类消息,queue是消息的物理管理单位,而topic是逻辑管理单位。一个topic下可以有多个queue,默认自动创建是4个,手动创建是8个
  • Message:消息,每个message必须指定一个topic
  • Broker:MQ程序,接收生产的消息,提供给消费者消费的程序
  • Name Server:给生产和消费者提供路由信息,提供轻量级的服务发现、路由、元数据信息,可以多个部署,互相独立(比zookeeper更轻量)
  • Offset: 偏移量,可以理解为消息进度
  • commit log: 消息存储会写在Commit log文件里面
message对象解读
  • topic: 主题名称
  • tag: 标签,用于过滤
  • key: 消息唯一标示,可以是业务字段组合
  • body: 消息体,字节数组

不同架构的rocketmq对比

  • 单节点。优点是,本地开发测试,配置简单,同步刷盘消息一条都不会丢。缺点是不可靠,如果宕机,会导致服务不可用
  • 主从(异步、同步双写) : 优点,同步双写消息不丢失, 异步复制存在少量丢失 ,主节点宕机,从节点可以对外提供消息的消费,但是不支持写入。缺点是主备有短暂消息延迟,毫秒级,目前不支持自动主从切换,需要脚本或者其他程序进行检测然后进行停止broker,重启让从节点成为主节点。
  • 双主。配置简单, 异步刷盘丢失少量消息。缺点是master机器宕机期间,未被消费的消息在机器恢复之前不可消费,实时性会受到影响。
  • 双主双从,多主多从模式(异步复制)。优点是磁盘损坏,消息丢失的非常少,消息实时性不会受影响,Master 宕机后,消费者仍然可以从Slave消费。缺点是主备有短暂消息延迟,毫秒级,如果Master宕机,磁盘损坏情况,会丢失少量消息。
  • 双主双从,多主多从模式(同步双写)。优点:同步双写方式,主备都写成功,向应用才返回成功,服务可用性与数据可用性都非常高。缺点:性能比异步复制模式略低,主宕机后,备机不能自动切换为主机。
消息复制机制

消息复制指的是从节点以什么样的方式同步主节点的消息。

同步复制,则表示,生产者发送消息到broker master节点,需要等slave节点将数据同步到节点后,才告诉生产者消息发送成功。这种就性能稍低。

异步复制,表示,生产者将消息发送到 broker master节点后,broker立马响应消息发送成功。slave 复制 master的消息是异步完成的。 因此这种方式性能稍高。但是也存在一定的风险。例如,消息发送到master返回成功后,在消息复制过程中,master宕机了,这时slave虽然可以提供消费,但是这条还未被复制到slave 的消息就丢失了。

消息持久化机制

消息持久化的意思是防止服务器重启或者完全宕机导致消息丢失采取的一种措施,例如将消息持久化到磁盘,当broker重启时不至于消息丢失。

同步持久化。意思是消息发送到服务端broker,收到消息后,要讲消息持久化到磁盘后,才响应客户端消息发送成功。此方式数据安全性高,但是性能比较低。

异步持久化。指的是消息到达服务端broker后,立马响应客户端消息发送成功。消息持久化的过程是异步完成的。这种方式性能比较高。但是存在风险。如果消息在持久化的过程中,此时broker突然宕机,就会导致消息丢失。

花式搭建 rocketmq

通用流程

  1. 下载 传送门自选版本。本文使用的是当前最新版本4.7.0,对应的包为 rocketmq-all-4.7.0-source-release.zip
  2. jdk,以及maven的安装过程就不在此赘述
  3. 解压,安装
yum install -y install unzip
yum install wget
wget https://archive.apache.org/dist/rocketmq/4.7.0/rocketmq-all-4.7.0-source-release.zip
unzip rocketmq-all-4.7.0-source-release.zip
cd rocketmq-all-4.7.0-source-release
mvn -Prelease-all -DskipTests clean install -U
  1. 修改NameServer与Broker启动所需要内存(防止机器配置不足启动失败)
# 1.进入主目录
cd rocketmq-all-4.7.0-source-release/distribution/target/rocketmq-4.7.0/rocketmq-4.7.0/
# 2.修改 nameserver 启动脚本
vim bin/runserver.sh
## 将 JAVA_OPT="${JAVA_OPT} -server -Xms4g -Xmx4g -Xmn2g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m" 改为
JAVA_OPT="${JAVA_OPT} -server -Xms256m -Xmx256m -Xmn256m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
# 修改 broker 启动脚本
vim bin/runbroker.sh
## 将 JAVA_OPT="${JAVA_OPT} -server -Xms8g -Xmx8g -Xmn4g" 改为
JAVA_OPT="${JAVA_OPT} -server -Xms512m -Xmx512m -Xmn256m"
  1. 关闭命令
sh bin/mqshutdown broker
sh bin/mqshutdown namesrv

安装rocketmq可视化控制台

  1. 下载 github传送门
  2. 源码安装
# 也可直接下载源码zip包
wget https://github.com/apache/rocketmq-externals/archive/master.zip
unzip master.zip
cd rocketmq-externals-master/rocketmq-console
# 修改spring工程的配置文件 
vim src/main/resources/application.properties 
# 修改springboot项目端口号,与nameserver地址
# server.port=8087
# rocketmq.config.namesrvAddr=127.0.0.1:9876
mvn clean install -DskipTests
cd target/
java -jar rocketmq-console-ng-1.0.1.jar
  1. 验证
    apache-rocketmq 学习笔记_第1张图片
单节点最简架构
  1. 启动NameServer与Broker
# 启动nameserver 日志显示 The Name Server boot success  表示成功
nohup sh bin/mqnamesrv &
tail -f ~/logs/rocketmqlogs/namesrv.log

# 启动 broker 日志显示 The broker[192.168.101.10, 172.17.0.1:10911] boot success. 表示成功
nohup sh bin/mqbroker -n 192.168.101.10:9876 -c conf/broker.conf &

# 也可用jps 命令查看java进程
[root@192 ~]# jps
21413 BrokerStartup
21355 NamesrvStartup
21487 Jps
[root@192 ~]# 
  1. 测试生产者发送消息
export NAMESRV_ADDR=localhost:9876
sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer
  1. 测试消费者消费消息
export NAMESRV_ADDR=localhost:9876
sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer

程序实际发送消息遇到的坑点

  1. 错误一,连接不上。org.apache.rocketmq.remoting.exception.RemotingTooMuchRequestException:
    sendDefaultImpl call timeout。原因1可能是部署机器上存在多块网卡,broker将服务注册到局域网中的网卡上了。具体可看控制台位置,看你客户端所在机器是否能访问到这里的 ip和端口。原因2可能是你服务端机器的防火墙导致,解决方案为关闭防火墙,或者开通防火墙策略。
    apache-rocketmq 学习笔记_第2张图片
# 原因1解决方案
# 1.编辑broker的配置文件
vim conf/broker.conf
# 2.添加一行,填上本机的外网访问ip地址
brokerIP1=192.168.101.10
# 3. 启动脚本增加参数
nohup sh bin/mqbroker -n 192.168.101.10:9876 -c conf/broker.conf &
  1. 发送消息时候报错,磁盘或者内存不足。
    com.alibaba.rocketmq.client.exception.MQBrokerException: CODE: 14 DESC: service not available now, maybe disk full, CL: 0.87 CQ: 0.87 INDEX: 0.87, maybe your broker machine memory too small。 此提示是服务器,磁盘不足或者,内存不足。笔者在这里遇到的是磁盘不足。 默认情况下,必须有4g的空闲磁盘才能正常提供服务。解决方案,方案1清理出磁盘,方案2 增加空闲磁盘。
主从架构搭建
  • broker 分为 master与slave 一个master可以对应多个slave,但一个slave只能对应一个master,master与slave通过相同的Broker Name来匹配,不同的broker Id来定义是master还是slave
  • Broker向所有的NameServer结点建立长连接,定时注册Topic和发送元数据信息
  • NameServer定时扫描(默认2分钟)所有存活broker的连接, 如果超过时间没响应则断开连接(心跳检测),但是consumer客户端不能感知,consumer定时(30s)从NameServer获取topic的最新信息,所以broker不可用时,consumer最多最需要30s才能发现
  • 只有master才能进行写入操作,slave不允许写入只能同步,同步策略取决于master的配置。
  • 客户端消费可以从master和slave消费,默认消费者都从master消费,如果在master挂后,客户端从NameServer中感知到Broker宕机,就会从slave消费, 感知非实时,存在一定的滞后性,slave不能保证master的消息100%都同步过来了,会有少量的消息丢失。但一旦master恢复,未同步过去的消息会被最终消费。
  • 如果consumer实例的数量比message queue的总数量还多的话,多出来的consumer实例将无法分到queue,也就无法消费到消息,也就无法起到分摊负载的作用,所以需要控制让queue的总数量大于等于consumer的数量
双主双重架构搭建

常用配置讲解

生产者配置
# broker所有配置都可以使用此命令查看
sh bin/mqbroker -m
# ----------------------- 
retryTimesWhenSendFailed : 失败重发次数
topicQueueNums : 主题下面的队列数量,默认是4
autoCreateTopicEnable : 是否自动创建主题Topic, 开发建议为true,生产要为false
defaultTopicQueueNums : 自动创建服务器不存在的topic,默认创建的队列数
brokerClusterName : 集群名称
brokerId : 0表示Master主节点 大于0表示从节点
brokerIP1 : Broker服务地址
brokerRole : broker角色 ASYNC_MASTER/ SYNC_MASTER/ SLAVE
deleteWhen : 每天执行删除过期文件的时间,默认每天凌晨4点
flushDiskType :刷盘策略, 默认为 ASYNC_FLUSH(异步刷盘), 另外是SYNC_FLUSH(同步刷盘)
listenPort : Broker监听的端口号
mapedFileSizeCommitLog : 单个conmmitlog文件大小,默认是1GB
storePathRootDir : 存储消息以及一些配置信息的根目录 默认为用户的 ${HOME}/store
storePathCommitLog:commitlog存储目录默认为${storePathRootDir}/commitlog
storePathIndex: 消息索引存储路径
syncFlushTimeout : 同步刷盘超时时间
diskMaxUsedSpaceRatio : 检测可用的磁盘空间大小,超过后会写入报错
生产者消息发送可能返回的状态
  1. 消息发送有同步和异步
  2. FLUSH_DISK_TIMEOUT 没有在规定时间内完成刷盘 (刷盘策略需要为SYNC_FLUSH 才会出这个错误)
  3. FLUSH_SLAVE_TIMEOUT 主从模式下,broker是SYNC_MASTER, 没有在规定时间内完成主从同步
  4. SLAVE_NOT_AVAILABLE 从模式下,broker是SYNC_MASTER, 但是没有找到被配置成Slave的Broker
  5. SEND_OK 发送成功,没有发生上面的三种问题
消费者配置
consumeFromWhere 初次消费起点
	CONSUME_FROM_FIRST_OFFSET: 初次从消息队列头部开始消费,即历史消息(还储存在broker的)全部消费一遍,后续再启动接着上次消费的进度开始消费
	CONSUME_FROM_LAST_OFFSET: 默认策略,初次从该队列最尾开始消费,即跳过历史消息,后续再启动接着上次消费的进度开始消费
	CONSUME_FROM_TIMESTAMP : 从某个时间点开始消费,默认是半个小时以前,后续再启动接着上次消费的进度开始消费
allocateMessageQueueStrategy 负载均衡策略,即消费者分配到queue的算法,默认值是AllocateMessageQueueAveragely 取模平均分配
consumeThreadMin 最小消费线程池数量
consumeThreadMax 最大消费线程池数量
pullBatchSize: 消费者去broker拉取消息时,一次拉取多少条。可选配置
consumeMessageBatchMaxSize: 单次消费时一次性消费多少条消息,批量消费接口才有用,可选配置
messageModel : 消费者消费模式, CLUSTERING——默认是集群模式CLUSTERING BROADCASTING——广播模式

rocketMq 理论学习

消息发送重试处理办法

  1. 生产者Producer重试(异步和SendOneWay下配置无效)。即消息重投,默认重试次数是2,可修改
  2. 消费端重试。消息处理异常,或者broker端到consumer端网络等各种问题,导致消费失败。重试间隔时间配置,默认每条消息最多重试16次。messageDelayLevel=1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h。超过次数后需要人工补偿。所以在消费端可能存在消费重复的消息。消费端需要对消息进行去重处理。另外需要注意的是,目前消费重试只针对集群消费方式有效,暂不支持方波方式重试。

消息发送模式

  1. ONEWAY : 无须等待响应,也没有回调。使用场景logServer抓取日志
  2. SYNC :同步发送,可靠性高,性能相对低一些。使用场景,营销,重要邮件通知等。
  3. ASYNC:异步发送,快,切可靠性高。比如注册账号后,同时增加几分服务等。

顺序消息(消息的生产和消费顺序一致)

  • 全局顺序:topic下面全部消息都要有序(少用)。性能低,严格按照FIFO进行消息发布与消费
  • 局部有序:保持一组消息被顺序消费即可。即一组消息在一个topic 的同一个queue中。例如 电商的订单创建,同一个订单相关的创建订单消息、订单支付消息、订单退款消息、订单物流消息、订单交易成功消息 都会按照先后顺序来发布和消费
  • 顺序发布:对于指定的一个 Topic,客户端将按照一定的先后顺序发送消息
  • 顺序消费:对于指定的一个 Topic,按照一定的先后顺序接收消息,即先发送的消息一定会先被客户端接收到。
  • 1.顺序消息暂不支持广播模式。2.顺序消息不支持异步发送方式,否则将无法严格保证顺序
  • 问题,如何保证 consumer 实例始终绑定在某个queue上

集群模式和广播模式

  • 集群模式。Consumer实例平均分摊消费生产者发送的消息,一个消息只被消费一次。
  • 广播模式。每个Consumer实例都会消费生产者投递到broker中的消息。
  • 切换模式。consumer.setMessageModel() 默认是集群模式

tag过滤方式

  • Broker端过滤,减少了无用的消息的进行网络传输,但是增加了broker的负担
  • Consumer端过滤,根据自身业务需求取出相应的消息,但是增加了很多无用的消息传输

消息消费方式

  • push 推。服务端主动将消息推送到consumer端。效率高,实时性高。但是增加了服务端的负载。为提高push方式的效率,push同样可以做缓存,攒够一定的数量再一次性发送。
  • pull 拉。consumer端主动去服务端拉取消息。主动权在客户端,可控性好。但是拉取的时间间隔需要控制好,不能太短(空拉,浪费资源)也不能太长(消息不能及时消费),有一种方式就是长轮询,拉一次保活15s。
  • PushConsumer 本质还是使用pull的方式实现的。 使用PullConsumer 需要自己维护Offset,处理不同状态的消息 FOUND、NO_NEW_MSG、OFFSET_ILLRGL、NO_MATCHED_MSG、4种状态。灵活性好,编码相对较复杂。主要是释放资源和保存Offset。

生产环境推荐配置

  • nameServer 配置多个不同节点
  • 多个Master,每个Master带有一个Slave
  • 主从设置为同步双写 SYN_MASTER
  • Producer 同步方式投递 broker
  • 持久化策略采用异步刷盘SYNC_FLUSH

rocketmq 实现分布式事务

发送事务消息 是利用了 rocketmq 中的半消息Half Message,半消息存在与broker中,但是不能被消费,只有等本地事务执行成功,二次确认后,半消息的状态才会转为正常可消费的消息。

本博文的github 各种消息demo参考地址
  • 同步发送消息
  • 异步发送消息
  • 发送延迟消息
  • 发送到指定topic的指定queue下
  • 发送顺序消息
  • 发送指定tag的 消息
  • 发送事务消息,实现分布式事务

总结

本文主要讲述了 rocketmq 的几种经典架构的搭建方式,以及rocketmq 的主要概念和配置讲解,还详细阐述了主从模式架构以及消息的复制模式和持久化模式。

你可能感兴趣的:(实战演练)