物联网实战|分布式MQTT集群
如何让多个独立运行的节点,就像一个整体一样协同工作
接入层
- 使用Nginx, HAProxy或云平台的SLB(如腾讯云CLB),将客户端连接分发到多个MQTT Broker
分布式MQTT集群的工作模式
- 连接与负载分发 海量 IoT 设备通过一个前置的负载均衡器(如 Nginx、HAProxy 或云平台 SLB)连接到集群,它将连接请求分发到不同的MQTT Broker节点上,避免单点过载
- 订阅关系同步 一个客户端连接到BrokerA,并订阅了主题 sensor/temperature,BrokerA会立即将此订阅信息同步给集群内的BrokerB和BrokerC。所有节点都维护一份全局的“主题-节点”订阅关系表
- 消息的路由与转发 当另一个客户端连接到BrokerB,并向sensor/temperature主题发布消息时
- BrokerB首先检查自己的订阅表,发现该主题的订阅者不在自己节点上,而是属于BrokerA
- BrokerB会通过节点间的内部通信通道,将消息转发给BrokerA
- BrokerA将消息投递给连接到它的订阅客户端

不同实操案例
集成Ignite
- 集成 Ignite节点启动时自动加入集群
- 客户端在节点A订阅主题,节点A将此订阅关系存入Ignite的分布式数据结构和缓存中,供所有节点共享
- 当节点B收到针对该主题的消息时,从Ignite查询订阅关系,若发现订阅者在节点A,则通过 Ignite 的服务网格将消息转发给节点A,最终由节点A投递给客户端
集成redis
- 订阅关系同步:将所有MQTT客户端的订阅关系存储到中心化的Redis,客户端连接到任意一个Netty Broker节点,该节点都会去查询并缓存这份全局订阅表
- 消息路由:当一个Broker节点收到Publish消息,它会从Redis全局订阅表中找到订阅了该主题的客户端位节点,当前节点,直接投递;其他节点,则通过内部消息通道将消息转发过去
- 会话与状态共享:将客户端的会话信息(Session)和QoS1/2的未确认消息存储在Redis中,保证当一个Broker节点宕机后,客户端重连到另一个节点时,可以无缝恢复会话,不会丢失消息
主要原因
Netty Channel对象本身无法在JVM间共享,分布式连接管理的核心就是通过一个中心化的状态存储redis来记录每个Channel所在的节点位置,然后根据这个位置信息在集群内进行消息路由和转发
