架构组成
Broker集群(代理服务器)
Broker用于主要负责消息的存储、投递和查询以及服务高可用保证。
- 接收生产者发送消息、消费者消费消息的请求。
- 存储消息相关的元数据,包括消费者组、消费进度偏移和主题和队列消息等
- 一个Broker集群由多组Master/Slave组成,Master可写可读,Slave只可以读,Master将写入的数据同步给Slave。
- 每个Broker节点,在启动时,都会遍历NameServer列表,与每个NameServer建立长连接,注册自己的信息,之后定时上报。
NameServer集群
NameServer是一个非常简单的Topic路由注册中心,其角色类似Dubbo中的zookeeper,支持Broker的动态注册与发现。通常会有多个实例部署,各实例间相互不进行信息通讯。Broker是向每一台NameServer注册自己的路由信息,所以每一个NameServer实例上面都保存一份完整的路由信息。当某个NameServer因某种原因下线了,客户端仍然可以向其它NameServer获取路由信息
主要包括两个功能:
- Broker管理,NameServer接受Broker集群的注册信息并且保存下来作为路由信息的基本数据。然后提供心跳检测机制,检查Broker是否还存活;
- 路由信息管理,每个NameServer将保存关于Broker集群的整个路由信息和用于客户端查询的队列信息。然后Producer和Conumser通过NameServer就可以知道整个Broker集群的路由信息,从而进行消息的投递和消费。
NameServer通常也是集群的方式部署,各实例间相互不进行信息通讯。Broker是向每一台NameServer注册自己的路由信息,所以每一个NameServer实例上面都保存一份完整的路由信息。当某个NameServer因某种原因下线了,Broker仍然可以向其它NameServer同步其路由信息,Producer,Consumer仍然可以动态感知Broker的路由的信息。
Producer集群
消息的生产者,通过NameServer集群获得Topic的路由信息,包括Topic下面有哪些Queue,这些Queue分布在哪些Broker上等。Producer只会将消息发送到Master节点上,因此只需要与Master节点建立连接。
Consumer集群
消息的消费者,通过NameServer集群获得Topic的路由信息,连接到对应的Broker上消费消息。注意,由于Master和Slave都可以读取消息,因此Consumer会与Master和Slave都建立连接。
DLedgerController(RocketMQ 5.0)
自动主从切换4.5版本已有,5.0再次优化
利⽤ Raft 选举出⼀个 Active DLedger Controller 作为主控制器,DLedger Controller 可以内嵌在 Nameserver中,也可以独立的部署。
其主要作用是,用来存储和管理 Broker 的 SyncStateSet 列表,并在某个 Broker 的 Master Broker 下线或⽹络隔离时,主动发出调度指令来切换 Broker 的 Master。
流程
- NameServer 互相独立,彼此没有通信关系,单台 NameServer 挂掉,不影响其他 NameServer。NameServer 不去连接别的机器,不主动推消息。
- 单个 Broker(Master、Slave) 与所有 NameServer 进行定时注册,以便告知 NameServer 自己还活着。
- Broker 每隔 30 秒向所有 NameServer 发送心跳,心跳包含了自身的 topic 配置信息。nameserver收到心跳包时会更新 brokerLiveTable 缓存中 BrokerLiveInfo 的 lastUpdataTimeStamp 信息
- NameServer 每隔 10 秒,扫描brokerLiveTable ,如果某个连接的最后更新时间与当前时间差值超过 120秒,则断开此连接,NameServer 也会断开此 broker 下所有与 slave 的连接。同时移除broker的路由信息,更新 topic 与队列的对应关系,但不通知生产者和消费者。
- 若Broker 正常关闭则执行 unregisterBroker 指令
- Consumer 随机与一个 NameServer 建立长连接,如果该 NameServer 断开,则从 NameServer 列表中查找下一个进行连接。
- Consumer 主要从 NameServer 中根据 Topic 查询 Broker 的地址,查到就会缓存到客户端,并向提供 Topic 服务的 Master、Slave 建立长连接,且定时向 Master、Slave 发送心跳。
- 如果 Broker 宕机,则 NameServer 会将其剔除,而 Consumer 端的定时任务 MQClientInstance.this.updateTopicRouteInfoFromNameServer 每 30 秒执行一次,将 Topic 对应的 Broker 地址拉取下来,此地址只有 Slave 地址了,此时 Consumer 从 Slave 上消费。
- 消费者与 Master 和 Slave 都建有连接,在不同场景有不同的消费规则。
- Producer 随机与一个 NameServer 建立长连接,每隔 30 秒(此处时间可配置)从 NameServer 获取 Topic 的最新队列情况,如果某个 Broker Master 宕机,Producer 最多 30 秒才能感知,在这个期间,发往该 broker master 的消息失败(此处失败有规避策略)。Producer 向提供 Topic 服务的 Master 建立长连接,且定时向 Master 发送心跳。
- 生产者与所有的 master 连接,但不能向 slave 写入。
- 客户端是先从 NameServer 寻址,得到可用 Broker 的 IP 和端口信息,然后据此信息连接 broker。
总结
Name Server 是专为 RocketMQ 设计的轻量级注册中心,只需具有数据一致性和发布订阅的功能。具有简单、可集群横吐扩展、无状态,节点之间互不通信(Zookeeper保证各节点数据强一致性会带来额外的性能消耗)等特点,
-
每个 Broker 与 NameServer 集群中的所有节点建立长连接,定时注册 Topic 信息到所有 NameServer。
-
Producer 与 NameServer 集群中的其中一个节点建立长连接,定期从 NameServer 获取Topic路由信息,并向提供 Topic 服务的 Master 建立长连接,且定时向 Master 发送心跳。Producer 完全无状态。
-
Consumer 与 NameServer 集群中的其中一个节点建立长连接,定期从 NameServer 获取 Topic 路由信息,并向提供 Topic 服务的 Master、Slave 建立长连接,且定时向 Master、Slave发送心跳。Consumer 既可以从 Master 订阅消息,也可以从Slave订阅消息。
消息模型
Topic
表示一类消息的集合,每个主题包含若干条消息,每条消息只能属于一个主题,是RocketMQ进行消息订阅的基本单位。
Message Queue
为了消息写入能力的水平扩展,RocketMQ 对 Topic进行了分区,用于并行发送和接收消息。同一个Topic下的数据,会分片保存到不同的Broker上,而每一个分片单位,就叫做MessageQueue,用于存储消息的物理地址,是生产者发