RocketMQ之NameServer
先来一段阿里云上的官方描述了解一下RocketMQ的部署架构和各个角色的概念
图中所涉及到的概念如下所述:
- Name Server: 是一个几乎无状态节点,可集群部署,在消息队列 MQ 中提供命名服务,更新和发现 Broker 服务。
- Broker:消息中转角色,负责存储消息,转发消息。分为 Master Broker 和 Slave Broker,一个 Master Broker 可以对应多个 Slave Broker,但是一个 Slave Broker 只能对应一个 Master Broker。Broker 启动后需要完成一次将自己注册至 Name Server 的操作;随后每隔 30s 定期向 Name Server 上报 Topic 路由信息。
- 生产者:与 Name Server 集群中的其中一个节点(随机)建立长链接(Keep-alive),定期从 Name Server 读取 Topic 路由信息,并向提供 Topic 服务的 Master Broker 建立长链接,且定时向 Master Broker 发送心跳。
- 消费者:与 Name Server 集群中的其中一个节点(随机)建立长连接,定期从 Name Server 拉取 Topic 路由信息,并向提供 Topic 服务的 Master Broker、Slave Broker 建立长连接,且定时向 Master Broker、Slave Broker 发送心跳。Consumer 既可以从 Master Broker 订阅消息,也可以从 Slave Broker 订阅消息,订阅规则由 Broker 配置决定。
其中的Name Server就有点类似服务注册发现的Eureka,Name Server分布式集群部署,可以保证高可用性,使用的是CAP理论中的AP架构,每台Name Server上都保存了所有Broker的路由信息,任何一台集群中的机器宕机,其他机器都可以继续提供服务。多个Name Server之间不通信,生产者,消费者和Broker都是与所有NameServer通信,且都是单向的,生产者和消费者是向Name Server请求数据,而Broker是向Name Server发送数据。
Name Server提供路由注册的功能,当Broker启动时,就会将Topic的各种信息传输到Name Server上,Name Server内部维护一个Broker表,动态存储Broker的消息。然后Broker每隔30s向Name Server发送心跳,并上传Topic路由信息,Name Server则会更新时间戳,记录这个Broker的最新存活时间。
Broker在正常情况下关闭的时候,会与Name Server断开长连接,Netty的通道关闭监听器会监听到连接断开事件,然后会将这个Broker信息剔除掉。异常情况下Broker宕机,Name Server每隔10s有一个定时任务会去检查Broker的最近心跳时间,如果发现超过120s都没有发送心跳的话,就认为Broker已经宕机了。
这里存在一个问题,生产者每隔30s从Name Server上获取最新的Broker信息,如果这时Broker异常下线的话,生产者还会向这个Broker中发送消息,无法保证消息发送的高可用性。解决办法是根据Broker的负载机制,默认使用的是轮询,如果消息发送失败的话,会异常重试,当一个Broker不行的时候,会选择另外一个Broker去发送消息。
Name Server相较于传统的分布式应用程序协调服务Zookeeper来说,RocketMQ并不需要使用到Zookeeper中的一些重量级功能,所以Name Server显得更加轻量级,代码较少,维护简单,同时稳定性也得到了很好的保证。