RocketMQ的注册中心
,用来保存topic-queue的路由信息,以及broker的实时配置信息。其他模块通过nameServer提供的接口获取最新的topic配置和路由信息;各nameServer之间不会互相通信,各nameServer都有完整的路由信息,即无状态。
Name Server 集群部署,但是节点之间并不会同步数据,因为每个节点都会保存完整的数据。因此单个节点挂掉,并不会对集群产生影响。
RocketMQ的核心模块,负责接收并存储消息
,同时提供push/pull接口来将消息发送给consumer。broker同时提供查询功能,可以通过messageId和messageKey来查询消息。broker会将自己的Topic配置信息实时同步到nameServer。相同brokerName的broker是一个组,其中brokerId未0的是master,其他是slave。
Broker 采用主从集群,实现多副本存储和高可用。每个 Broker 节点都要跟所有的 Name Server 节点建立长连接,定义注册 Topic 路由信息和发送心跳。
Consumer 跟 Name Server 的任意一个节点建立长连接,定期从 Name Server 拉取 Topic 路由信息。Consumer 是否采用集群,取决于它所在的业务系统。
proxy承接了客户端侧所有流量,broker和nameServer不再直接对用户暴露,用户唯一能看到的组件只有代理层。
proxy包括如下几个职责:
- 多协议适配
- 流量治理和流量分发
- 功能扩展
proxy两大特性
- 无状态,可以根据用户以及客户端的流量进行水平扩缩容
- 计算型,比较小号CPU,因此在部署的时候需要尽可能多分配一些CPU
主题是 Apache RocketMQ 中消息传输和存储的顶层容器
,用于标识同一类业务逻辑的消息。所有消息资源的定义都在主题内部完成,但主题是一个逻辑概念
,并不是实际的消息容器
。
主题的作用主要如下:
- 定义数据的分类隔离: 在 Apache RocketMQ 的方案设计中,建议
将不同业务类型的数据拆分到不同的主题中
管理,通过主题实现存储的隔离性和订阅隔离性。- 定义数据的身份和权限: Apache RocketMQ 的消息本身是匿名无身份的,
同一分类的消息使用相同的主题来做身份识别和权限管理
。
主题内部由多个队列组成,消息的存储和水平扩展能力最终是由队列实现的;针对主题的所有约束和属性设置,最终也是通过主题内部的队列来实现。
内部属性
- 主题名称:主题的名称,用于标识主题,
主题名称集群内全局唯一
。- 队列列表:一个主题内包含一个或多个队列,消息实际存储在主题的各队列内。
系统根据队列数量给主题分配队列
,队列数量创建主题时定义。- 消息类型:Apache RocketMQ 支持的主题类型如下:
Normal:普通消息,消息本身无特殊语义,消息之间也没有任何关联。
FIFO:顺序消息,Apache RocketMQ 通过消息分组MessageGroup标记一组特定消息的先后顺序,可以保证消息的投递顺序严格按照消息发送时的顺序。
Delay:定时/延时消息,通过指定延时时间控制消息生产后不要立即投递,而是在延时间隔后才对消费者可见。
Transaction:事务消息,Apache RocketMQ 支持分布式事务消息,支持应用数据库更新和消息调用的事务一致性保障。
队列是 Apache RocketMQ 中消息存储和传输的实际容器
,也是 Apache RocketMQ 消息的最小存储单元
。 Apache RocketMQ 的所有主题都是由多个队列组成,以此实现队列数量的水平拆分和队列内部的流式存储。
队列的主要作用如下:
- 存储顺序性:队列天然具备
顺序性
,即消息按照进入队列的顺序写入存储,同一队列间的消息天然存在顺序关系
,队列头部为最早写入的消息,队列尾部为最新写入的消息。消息在队列中的位置和消息之间的顺序通过位点(Offset)进行标记管理- 流式操作语义:Apache RocketMQ
基于队列的存储模型可确保消息从任意位点读取任意数量的消息
,以此实现类似聚合读取、回溯读取等特性,这些特性是RabbitMQ、ActiveMQ等非队列存储模型不具备的。
内部属性
- 读写权限:由服务端定义,枚举值如下
6:读写状态,当前队列允许读取消息和写入消息。
4:只读状态,当前队列只允许读取消息,不允许写入消息。
2:只写状态,当前队列只允许写入消息,不允许读取消息。
0:不可读写状态,当前队列不允许读取消息和写入消息。
消息是 Apache RocketMQ 中的最小数据传输单元
。生产者将业务数据的负载和拓展属性包装成消息发送到 Apache RocketMQ 服务端,服务端按照相关语义将消息投递到消费端进行消费。
消息内部属性
- 主题名称:当前消息所属的主题的名称。集群内全局唯一。从客户端SDK接口获取。
- 消息类型:从客户端SDK接口获取。Apache RocketMQ 支持的消息类型如下:
Normal:普通消息,消息本身无特殊语义,消息之间也没有任何关联。
FIFO:顺序消息,Apache RocketMQ 通过消息分组MessageGroup标记一组特定消息的先后顺序,可以保证消息的投递顺序严格按照消息发送时的顺序。
Delay:定时/延时消息,通过指定延时时间控制消息生产后不要立即投递,而是在延时间隔后才对消费者可见。
Transaction:事务消息,Apache RocketMQ 支持分布式事务消息,支持应用数据库更新和消息调用的事务一致性保障。
- 消息队列:实际存储当前消息的队列。
由服务端指定并填充
。- 消息位点:当前消息存储在队列中的位置。
由服务端指定并填充
。取值范围:0~long.Max。- 消息ID:
消息的唯一标识
,集群内每条消息的ID全局唯一。生产者客户端系统自动生成
。固定为数字和大写字母组成的32位字符串。- 索引Key列表(可选):消息的索引键,可通过设置不同的Key区分消息和快速查找消息。
由生产者客户端定义
。- 过滤标签Tag(可选):消息的过滤标签。消费者可通过Tag对消息进行过滤,仅接收指定标签的消息。
由生产者客户端定义
。一条消息仅支持设置一个标签
。- 定时时间(可选):定时场景下,消息触发延时投递的毫秒级时间戳。由消息生产者定义。最大可设置定时时长为40天。
- 消息发送时间:消息发送时,生产者客户端系统的本地毫秒级时间戳。由生产者客户端系统填充。说明:客户端系统时钟和服务端系统时钟可能存在偏差,消息发送时间是以客户端系统时钟为准。
- 消息保存时间戳:消息在Apache RocketMQ 服务端完成存储时,服务端系统的本地毫秒级时间戳。 对于定时消息和事务消息,消息保存时间指的是消息生效对消费方可见的服务端系统时间。由服务端系统填充。说明:客户端系统时钟和服务端系统时钟可能存在偏差,消息保留时间是以服务端系统时钟为准。
- 消费重试次数:消息消费失败后,Apache RocketMQ 服务端重新投递的次数。每次重试后,重试次数加1。由服务端系统标记。首次消费,重试次数为0;消费失败首次重试时,重试次数为1。
- 业务自定义属性:生产者可以自定义设置的扩展信息。由消息生产者自定义,按照字符串键值对设置。
- 消息负载:业务消息的实际报文数据。由生产者负责序列化编码,按照二进制字节传输。
生产者是 Apache RocketMQ 系统中用来构建并传输消息到服务端的运行实体。生产者和主题的关系为多对多关系
,即同一个生产者可以向多个主题发送消息,对于平台类场景如果需要发送消息到多个主题,并不需要创建多个生产者;同一个主题也可以接收多个生产者的消息,以此可以实现生产者性能的水平扩展和容灾。
Producer 跟 Name Server 的任意一个节点建立长连接,定期从 Name Server 拉取 Topic 路由信息。Producer 是否采用集群,取决于它所在的业务系统。
内部属性
- 客户端ID:生产者客户端的标识,用于区分不同的生产者。
集群内全局唯一
。客户端ID由Apache RocketMQ 的SDK自动生成,主要用于日志查看、问题定位等运维场景,不支持修改。- 通信参数:
- 接入点信息 (必选) :连接服务端的接入地址,用于识别服务端集群。 接入点必须按格式配置,建议使用域名,避免使用IP地址,防止节点变更无法进行热点迁移。
- 身份认证信息 (可选) :客户端用于身份验证的凭证信息。 仅在服务端开启身份识别和认证时需要传输。
- 请求超时时间 (可选) :客户端网络请求调用的超时时间。取值范围和默认值,请参见参数限制。
- 预绑定主题列表:Apache RocketMQ 的生产者需要将消息发送到的目标主题列表,主要作用如下:
- 事务消息 (必须设置) :事务消息场景下,生产者在故障、重启恢复时,需要检查事务消息的主题中是否有未提交的事务消息。避免生产者发送新消息后,主题中的旧事务消息一直处于未提交状态,造成业务延迟。
- 非事务消息 (建议设置) :服务端会在生产者初始化时根据预绑定主题列表,检查目标主题的访问权限和合法性,而不需要等到应用启动后再检查。
约束:对于事务消息,预绑定列表必须设置,且需要和事务检查器一起配合使用
。若未设置,或后续消息发送的目标主题动态变更, Apache RocketMQ 会对目标主题进行动态补充检验。- 事务检查器:Apache RocketMQ 的事务消息机制中,为保证异常场景下事务的最终一致性,生产者需要主动实现事务检查器的接口。发送事务消息时,事务检查器必须设置,且需要和预绑定主题列表一起配合使用。
- 发送重试策略:生产者在消息发送失败时的重试策略。
消费者分组是 Apache RocketMQ 系统中承载多个消费行为一致的消费者的负载均衡分组
。
和消费者不同,消费者分组并不是运行实体,而是一个逻辑资源
。在 Apache RocketMQ 中,通过消费者分组内初始化多个消费者实现消费性能的水平扩展以及高可用容灾
。
在消费者分组中,统一定义以下消费行为,
同一分组下的多个消费者将按照分组内统一的消费行为和负载均衡策略消费消息
。
- 订阅关系:Apache RocketMQ 以消费者分组的粒度管理订阅关系,实现订阅关系的管理和追溯。
- 投递顺序性:Apache RocketMQ 的服务端将消息投递给消费者消费时,支持顺序投递和并发投递,投递方式在消费者分组中统一配置。
- 消费重试策略: 消费者消费消息失败时的重试策略,包括重试次数、死信队列设置等。
消费者是 Apache RocketMQ 中用来接收并处理消息的运行实体
。 消费者通常被集成在业务系统中,从 Apache RocketMQ 服务端获取消息,并将消息转化成业务可理解的信息,供业务逻辑处理。
在消息消费端,可以定义如下传输行为:
- 消费者身份:
消费者必须关联一个指定的消费者分组
,以获取分组内统一定义的行为配置和消费状态。- 消费者类型:Apache RocketMQ 面向不同的开发场景提供了多样的消费者类型,包括PushConsumer类型、SimpleConsumer类型、PullConsumer类型(仅推荐流处理场景使用)等。具体信息,请参见消费者分类。
- 消费者本地运行配置:消费者根据不同的消费者类型,控制消费者客户端本地的运行配置。例如消费者客户端的线程数,消费并发度等,实现不同的传输效果。
内部属性
- 消费者分组名称:当前消费者关联的消费者分组名称,消费者必须关联到指定的消费者分组,通过消费者分组获取消费行为。消费者分组为Apache RocketMQ 的逻辑资源,需要您提前通过控制台或OpenAPI创建。
- 客户端ID:消费者客户端的标识,用于区分不同的消费者。集群内全局唯一。客户端ID由Apache RocketMQ 的SDK自动生成,主要用于日志查看、问题定位等运维场景,不支持修改。
- 通信参数:
- 接入点信息 (必选) :
连接服务端的接入地址
,用于识别服务端集群。 接入点必须按格式配置,建议使用域名
,避免使用IP地址,防止节点变更无法进行热点迁移。- 身份认证信息 (可选) :客户端用于身份验证的凭证信息。 仅在服务端开启身份识别和认证时需要传输。
- 请求超时时间 (可选) :客户端网络请求调用的超时时间。取值范围和默认值,请参见参数限制。
- 预绑定订阅关系列表:指定消费者的订阅关系列表。 Apache RocketMQ 服务端可在消费者初始化阶段,根据预绑定的订阅关系列表对目标主题进行权限及合法性校验,无需等到应用启动后才能校验。
建议在消费者初始化阶段明确订阅关系即要订阅的主题列表
,若未设置,或订阅的主题动态变更,Apache RocketMQ 会对目标主题进行动态补充校验。- 消费监听器:Apache RocketMQ 服务端将消息推送给消费者后,消费者调用消息消费逻辑的监听器。由消费者客户端本地配置。
使用PushConsumer类型的消费者消费消息时,消费者客户端必须设置消费监听器
。消费者类型的具体信息,请参见消费者分类。
订阅关系是 Apache RocketMQ 系统中消费者获取消息、处理消息的规则和状态配置
。
订阅关系由消费者分组动态注册到服务端系统
,并在后续的消息传输中按照订阅关系定义的过滤规则进行消息匹配和消费进度维护。
通过配置订阅关系,可控制如下传输行为:
- 消息过滤规则:用于控制消费者在消费消息时,选择主题内的哪些消息进行消费,设置消费过滤规则可以高效地过滤消费者需要的消息集合,灵活根据不同的业务场景设置不同的消息接收范围。具体信息,请参见消息过滤。
- 消费状态:Apache RocketMQ 服务端默认提供订阅关系持久化的能力,即消费者分组在服务端注册订阅关系后,当消费者离线并再次上线后,可以获取离线前的消费进度并继续消费。
订阅关系判断原则
Apache RocketMQ 的订阅关系按照消费者分组和主题粒度设计
,因此,一个订阅关系指的是指定某个消费者分组对于某个主题的订阅
,判断原则如下:
内部属性
- 过滤类型:消息过滤规则的类型。订阅关系中设置消息过滤规则后,系统将按照过滤规则匹配主题中的消息,只将符合条件的消息投递给消费者消费,实现消息的再次分类。
取值:
- TAG过滤:按照Tag字符串进行全文过滤匹配。
- SQL92过滤:按照SQL语法对消息属性进行过滤匹配。
- 过滤表达式:自定义的过滤规则表达式。取值:具体取值规范,请参见过滤表达式语法规范。
部署模式 | 说明 | 优点 | 缺点 |
---|---|---|---|
单节点单副本模式 | 这种方式风险较大,因为 Broker 只有一个节点,一旦Broker重启或者宕机时,会导致整个服务不可用。不建议线上环境使用, 可以用于本地测试。 | ||
多节点单副本模式 | 一个集群内全部部署 Master 角色,不部署Slave 副本,例如2个Master或者3个Master | 配置简单,单个Master宕机或重启维护对应用无影响,在磁盘配置为RAID10时,即使机器宕机不可恢复情况下,由于RAID10磁盘非常可靠,消息也不会丢(异步刷盘丢失少量消息,同步刷盘一条不丢),性能最高; | 单台机器宕机期间,这台机器上未被消费的消息在机器恢复之前不可订阅,消息实时性会受到影响。 |
多节点多副本模式 异步复制 | 每个Master配置一个Slave,有多组 Master-Slave,HA采用异步复制方式,主备有短暂消息延迟(毫秒级) | 即使磁盘损坏,消息丢失的非常少,且消息实时性不会受影响,同时Master宕机后,消费者仍然可以从Slave消费,而且此过程对应用透明,不需要人工干预,性能同多Master模式几乎一样; | Master宕机,磁盘损坏情况下会丢失少量消息。 |
多节点多副本模式 同步双写 | 每个Master配置一个Slave,有多对 Master-Slave,HA采用同步双写方式,即只有主备都写成功,才向应用返回成功 | 数据与服务都无单点故障,Master宕机情况下,消息无延迟,服务可用性与数据可用性都非常高; | 性能比异步复制模式略低(大约低10%左右),发送单个消息的RT会略高,且目前版本在主节点宕机后,备机不能自动切换为主机。 |
Local 模式下 Proxy 和 Broker 是同进程部署,Proxy本身无状态。
unzip openjdk1.8_x86_64.zip
chmod a+x /opt/openjdk1.8/bin/*
chmod a+x /opt/openjdk1.8/jre/bin/*
cat >> /etc/profile << EOF
export JAVA_HOME=/opt/openjdk1.8
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
EOF
source /etc/profile
### 解压源码包
unzip rocketmq-all-5.0.0-bin-release.zip
cd ./rocketmq-all-5.0.0-bin-release
NameServer需要先于Broker启动,且如果在生产环境使用,为了保证高可用,建议一般规模的集群启动3个NameServer,各节点的启动命令相同,如下:
### 首先启动NameServer
$ nohup sh bin/mqnamesrv &
### 验证Name Server 是否启动成功
$ tail -f ~/logs/rocketmqlogs/namesrv.log
The Name Server boot success...
### 在机器A,启动第一个Master,例如NameServer的IP为:192.168.1.1
### 修改broker配置,在最后一行加上namesrvAddr配置
$ vim $ROCKETMQ_HOME/conf/2m-2s-async/broker-a.properties
# 所属集群名称
brokerClusterName=DefaultCluster
# broker名称
brokerName=broker-a
# 0表示master,>0表示slave
brokerId=0
# 删除文件时间点,默认凌晨4点
deleteWhen=04
# 文件保留时间,默认48小时
fileReservedTime=48
# broker角色
# 1、ASYNC_MASTER:异步复制master
# 2、SYNC_MASTER:同步双写master
# 3、SLAVE
brokerRole=ASYNC_MASTER
# 刷盘方式
# 1、ASYNC_FLUSH:异步刷盘
# 2、SYNC_FLUSH:同步刷盘
flushDiskType=ASYNC_FLUSH
# nameServer地址,分号分隔
namesrvAddr=10.243.9.100:9876;10.243.9.77:9876;10.243.9.189:9876;10.243.9.180:9876
$ nohup sh ./bin/mqbroker -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-a.properties --enable-proxy &
### 验证broker是否启动成功, 比如, broker的ip是192.168.1.2 然后名字是broker-a
$ tail -f ~/logs/rocketmqlogs/broker_default.log
The broker[broker-a,192.169.1.2:10911] boot success...
### 在机器B,启动第二个Master
$ nohup sh ./bin/mqbroker -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-b.properties --enable-proxy &
### 在机器C,启动第一个Slave
$ nohup sh ./bin/mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-a-s.properties --enable-proxy &
### 在机器D,启动第二个Slave
$ nohup sh ./bin/mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-b-s.properties --enable-proxy &
提示
以上 Broker 与 Slave 配对是通过指定相同的 BrokerName 参数来配对,Master 的 BrokerId 必须是 0,Slave 的 BrokerId 必须是大于 0 的数。另外一个 Master 下面可以挂载多个 Slave,同一 Master 下的多个 Slave 通过指定不同的 BrokerId 来区分。$ROCKETMQ_HOME
指的RocketMQ安装目录,需要用户自己设置此环境变量。