4. EMQX集群内部通信与路由
EMQX 集群并不是把多台 Broker 简单堆在一起,而是让每个节点都持有一份“全局视图”:谁在线、哪些主题被订阅、消息该往哪里投。理解这套内部机制,才能判断扩容、跨机房部署和网络抖动时系统会如何表现。本节围绕四个核心问题展开:节点之间怎么通信、主题树和订阅关系如何同步、消息如何被转发、网络分区时会发生什么。
一、节点间通信:全互联与集群路由表
EMQX 集群默认采用全互联(full mesh)拓扑,每个节点与其它所有节点建立 Erlang 分布式连接。节点通过 ekka 库维护集群成员关系,节点名形如 emqx@10.0.0.11,其中 @ 后为节点标识。集群建立后,每个节点都保存一张全局路由表,记录“主题 → 订阅该主题的节点集合”。
节点发现方式常见有三种:手动 cluster.static.seeds 静态种子、DNS 自动发现、以及 Kubernetes 等环境下的 etcd/K8s 发现。以静态种子为例:
cluster {
name = emqxcl
discovery_strategy = manual
static.seeds = ["emqx@10.0.0.11", "emqx@10.0.0.12"]
}
节点启动后向种子节点发起连接,成功后通过 gossip 协议把新成员扩散到全网。可用 emqx ctl cluster status 查看成员与连接状态,正常时所有节点应显示 running。
二、主题树同步与订阅关系传播
EMQX 内部用主题树(Topic Trie)组织订阅,节点按 / 分层匹配。当客户端在节点 A 订阅 sensor/room1/temp 时,节点 A 会更新本地主题树,并把这条订阅关系广播给集群内其它节点,使每个节点的路由表都记录“该主题有节点 A 的订阅者”。这样任意节点收到消息时,都能直接判断需要转发到哪些节点,而不必逐节点询问。
订阅传播有两种典型模式:
- 全量广播:订阅变更直接同步到所有节点,路由表始终一致,适合节点数较少(如 3~7 个)的集群。
- 分片/代理路由:在大规模集群中,订阅关系按主题哈希分布到不同节点,减少广播风暴,但会增加一次路由跳转。
需要注意,订阅关系传播是异步的。节点 A 刚订阅完,节点 B 的路由表可能还没更新,这段时间内从 B 发布的消息可能不会立即投递给 A 的订阅者。这是正常现象,通常毫秒级完成,但在网络抖动时会拉长。
三、消息转发策略:发布路径与投递路径
消息转发遵循“发布节点查表、按需转发”的原则。假设客户端 P 连接节点 A,发布主题 sensor/room1/temp:
- 节点 A 收到 PUBLISH,先匹配本地订阅者,若有则直接投递。
- 节点 A 查询全局路由表,发现节点 B 也有订阅者,于是把消息转发给节点 B。
- 节点 B 收到转发消息后,投递给本地订阅该主题的客户端。
- 若路由表中没有其它节点,则消息不再跨节点转发。
转发时 QoS 会影响可靠性:QoS 0 尽力而为,QoS 1 至少一次,QoS 2 恰好一次。跨节点转发会保留原始 QoS,但节点间链路异常时,QoS 1/2 消息可能进入重传队列。可用 emqx ctl broker metrics 观察 messages.sent、messages.dropped 等指标判断转发是否健康。
$share/group/topic)会把同一组的订阅者分散到多个节点,消息只投递给组内一个订阅者,常用于负载均衡消费。此时路由表记录的是“组 → 节点集合”,转发策略会额外做一次组内选主。四、网络分区的影响与应对
网络分区指集群节点之间网络中断,但各节点仍能对外服务。EMQX 默认使用 autoheal 策略:分区后各子集群独立运行,网络恢复后自动合并。分区期间会出现两类问题:
- 路由表不一致:分区两侧各自维护路由表,跨区订阅的消息无法投递,表现为“消息丢失”或“订阅者收不到”。
- 会话状态分裂:若客户端重连到另一侧节点,会话可能被重建,QoS 1/2 的未确认消息可能重复或丢失。
判断是否发生分区,可查看 emqx ctl cluster status 中节点是否变为 stopped 或 disconnected,并观察日志中的 netsplit 关键字。生产环境建议:
| 场景 | 建议策略 | 关键参数 |
|---|---|---|
| 同机房 3 节点 | 全互联 + autoheal | cluster.autoheal = true |
| 跨机房双活 | 分区时禁止自动合并,人工确认 | cluster.autoheal = false |
| 大规模集群 | 分片路由 + 核心/边缘分层 | cluster.core_nodes / replicant |
总结来看,EMQX 集群内部通信的核心是“全局路由表 + 异步订阅传播 + 按需转发”。节点越多,广播开销越大;网络越不稳定,路由表一致性越难保证。实际部署中应根据节点规模、机房分布和可靠性要求,在“全互联简单一致”与“分片路由可扩展”之间做取舍,并为网络分区准备好明确的处理策略。