Apache RocketMQ是一款具有低延迟,高性能和可靠性,数十亿容量和灵活可扩展性的分布式消息传递和流媒体平台。它由NameServer、Broker、Producer以及Consumer四部分构成
消息中间件是利用高效可靠的消息传递机制进行平台无关的数据通信来达到分布式系统的集成目的,通过提供消息传递和消息排队模型,可以在分布式架构下扩展进程之间的通信。对于消息中间件,常见的角色就是Producer(生产者)、Consumer(消费者) 、broker(消息中间件实例)。
异步与解耦
流量削峰
数据分发
执行流程:
- 启动 NameServer,NameServer 启动后监听端口,等待 Broker、Producer、Consumer 连上来,相当于一个路由控制中心。
- Broker 启动,跟所有的 NameServer 保持长连接,定时发送心跳包。心跳包中包含当前 Broker 信息(IP+端口等)以及存储所有Topic信息。注册成功后,NameServer 集群中就有 Topic 跟 Broke r的映射关系。
- 收发消息前,先创建 Topic,创建 Topic 时需要指定该 Topic 要存储在哪些 Broker 上,也可以在发送消息时自动创建 Topic。
- Producer 发送消息,启动时先跟 NameServer 集群中的其中一台建立长连接,并从 NameServer 中获取当前发送的 Topic 存在哪些 Broker 上,轮询从队列列表中选择一个队列,然后与队列所在的 Broker 建立长连接从而向
Broker 发消息。- Consumer 跟 Producer 类似,跟其中一台 NameServer 建立长连接,获取当前订阅 Topic 存在哪些 Broker 上,然后直接跟 Broker 建立连接通道,开始消费消息。
RocketMQ 需要先启动NameServer,再启动 RocketMQ 中的 Broker。
nameserver的底层是由netty实现:提供路由管理、服务注册、服务发现的功能,是一个无状态的节点
nameserver作为服务的发现者:集群中的各个角色(producer、broker、consumer)都要定时的向nameserver上报自己的状态,以便互相发现彼此,超时不上报会从列表中剔除。
nameserver可以集群化部署:当有多个nameserver存在时,其他角色会同时向他们上报信息,这样可以保证nameserver的高可用性,他们之间互不通信,没有主从的关系。
broker面向producer(发送消息)、consumer(接受消息),broker需要向nameserver提交自己的信息,是消息中间件的消息存储器和消息转发器。每个broker在启动的时候都会遍历nameserver的列表,与每一个nameserver建立连接,注册自己的信息,之后定时向每一个nameserver上报。
producer是消息的生产者,通过集群中的任意一个(nameserver)节点(随机选择)建立长连接,获取topic的路由信息【包括Topic下有那些queue,这些queue分布在哪些broker上等等】。接下来向提供topic服务的master(broker)建立长连接,且定时发心跳。
consumer和nameserver保持连接,每隔30s将会从nameserver服务器中查询topic路由信息,查询到路由信息信息后,就会根据ip映射件从broker中消费消息。跟broker的连接也是30s向broker发送跳检测
消息(Message):生产或消费的数据,对于 RocketMQ 来说,消息就是字节数组。
主题(Topic):区分消息的种类,标识一类消息的逻辑名字,消息的逻辑管理单位。无论消息生产还是消费,都需要指定 Topic。
消息队列(Message Queue):简称 Queue 或 Q,消息物理管理单位。用于并行发送和接收消息,相当于是Topic的分区。
一个 Topic 将有若干个 Q。若一个 Topic 创建在不同的 Broker,则不同的 broker 上都有若干 Q,消息将物理地存储落在不同 Broker 结点上,具有水平扩展的能力。
无论生产者还是消费者,实际的生产和消费都是针对 Q 级别。
注意: 在 RocketMQ 中,所有消息队列都是持久化的,长度无限的数据结构,所谓长度无限是指队列中的每个存储单元都是定长,访问其中的存储单元使用Offset来访问,offset为 java long 类型,64 位,理论上在 100年内不会溢出,所以认为为是长度无限,另外队列中只保存最近几天的数据,之前的数据会按照过期时间来删除。也可以认为Message Queue是一个长度无限的数组,offset 就是下标。
Group 分为两个部分 生产者和消费者
RocketMQ 支持在发送时给 topic 的消息设置 tag,用于同一主题下区分不同类型的消息。
来自同一业务单元的消息,可以根据不同业务目的在同一主题下设置不同标签。
比如有一个 Topic 消息为水果,那么水果可以有其他的标签 可以是 香蕉、西瓜、草莓等等,我们可以把对应的消息,打上对应的标签(Tag),这个就是方便我们在消费的时候做对应的筛选。
标签能够有效地保持代码的清晰度和连贯性,并优化 RocketMQ 提供的查询系统。消费者可以根据Tag实现对不同子主题的不同消费逻辑,实现更好的扩展性。
在 RocketMQ 中,有很多 offset 的概念。一般我们只关心暴露到客户端的offset。不指定的话,一般指的是消费者消息的偏移量(ConsumerOffset)
Message queue 是无限长的数组。一条消息进来下标就会涨 1,而这个数组的下标就是 offset。
Message queue 中的 max offset 表示消息的最大 offset,Consumer offset 可以理解为标记 Consumer Group 在一条逻辑 Message Queue 上,消息消费到哪里即消费进度。
基本概念参考:Apache RocketMQ中文文档