基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

RocketMQ的NameServer 是如何感知 Broker 的存活状态的?

RocketMQ 的 NameServer 感知 Broker 存活状态主要依赖于 心跳机制(定时上报与超时剔除) 以及 底层网络事件驱动(Netty 长连接状态异常) 两个层面的配合。

具体来说,整个过程可以分为以下几个核心环节:

1. Broker 定时发送心跳(主动上报)

  • 注册与心跳发送:Broker 在启动时,会向所有的 NameServer 节点发起注册请求。启动成功后,Broker 会开启一个定时任务,默认每隔 30 秒向集群中所有的 NameServer 发送心跳包(RegisterBroker Request)。
  • 心跳内容:心跳包中不仅包含 Broker 的基础信息(如 Broker 名称、集群名称、IP 地址、主备角色等),还会携带该 Broker 上所有的 Topic 配置信息(如果 Topic 较多,会对数据进行压缩)。

2. NameServer 接收并维护状态(更新时间戳)

  • 核心数据结构:NameServer 内部有一个非常核心的类叫 RouteInfoManager,里面维护了一个名为 brokerLiveTable 的哈希表(HashMap)。
    • Key:Broker 的地址(IP:Port)。
    • ValueBrokerLiveInfo 对象,里面包含了一个至关重要的属性 —— lastUpdateTimestamp(最后一次收到心跳的时间戳)。
  • 更新时间戳:每当 NameServer 收到 Broker 发来的心跳包时,就会更新 brokerLiveTable 中对应 Broker 的 lastUpdateTimestamp 为当前系统时间。

3. NameServer 定时扫描与超时剔除(兜底机制)

  • 定时扫描:NameServer 自身也会启动一个定时任务,默认每隔 10 秒执行一次扫描。
  • 剔除逻辑:它会遍历 brokerLiveTable,检查每一个 Broker 的 lastUpdateTimestamp
  • 判定死亡:如果 NameServer 发现当前时间减去 lastUpdateTimestamp 的值 大于 120 秒(即连续两分钟没收到该 Broker 的心跳),NameServer 就会认为该 Broker 已经宕机(下线)。
  • 清理路由:一旦判定 Broker 死亡,NameServer 会关闭与该 Broker 的连接,并将其从 brokerLiveTablebrokerAddrTableclusterAddrTable 等所有路由表中剔除。这样,后续的 Producer 和 Consumer 就无法再获取到该 Broker 的路由信息了。

4. 基于 Netty 的网络事件监听(实时感知)

除了上述的定时扫描机制,RocketMQ 还利用了底层通信框架 Netty 的长连接特性来实现更实时的感知

  • NameServer 和 Broker 之间是通过 Netty 建立的 TCP 长连接。
  • NameServer 会监听 Netty Channel 的状态事件(如 ChannelInactive 连接断开、ChannelException 发生异常、ChannelIdle 状态空闲等)。
  • 快速剔除:如果 Broker 进程非正常退出(比如被 kill -9 杀掉)或者网络突然中断导致 TCP 连接断开,NameServer 的 Netty 监听器会立刻捕获到连接断开事件,不需要等待 120 秒超时,而是会立刻触发路由清理逻辑,将该 Broker 从路由表中移除。

总结

NameServer 感知 Broker 存活主要靠两条腿走路:

  1. 正常/网络拥塞情况(心跳+超时):Broker 每 30s 发心跳,NameServer 每 10s 查一次,超过 120s 没收到心跳就踢掉。
  2. 异常断开情况(网络事件驱动):Broker 进程奔溃导致 TCP 连接断开,NameServer 底层 Netty 立刻触发 channelInactive 事件,瞬间将 Broker 剔除,保证了路由信息的实时性。
00:00
00:00