分布集群 (Clustering)
注:大部分是摘自EMQ官网,部分根据自己的实践进行完善
EMQ R2 分布集群设计
EMQ 消息服务器集群基于 Erlang/OTP 分布式设计,集群原理可简述为下述两条规则:
- MQTT 客户端订阅主题时,所在节点订阅成功后广播通知其他节点:某个主题(Topic)被本节点订阅。
- MQTT 客户端发布消息时,所在节点会根据消息主题(Topic),检索订阅并路由消息到相关节点。
EMQ 消息服务器同一集群的所有节点,都会复制一份主题(Topic) -> 节点(Node)映射的路由表,例如:
topic1 -> node1, node2 topic2 -> node3 topic3 -> node2, node4
主题树(Topic Trie)与路由表(Route Table)
EMQ 消息服务器每个集群节点,都保存一份主题树(Topic Trie)和路由表。
例如下述主题订阅关系:
客户端 | 节点 | 订阅主题 |
client1 | node1 | t/+/x, t/+/y |
client2 | node2 | t/# |
client3 | node3 | t/+/x, t/a |
最终会生成如下主题树(Topic Trie)和路由表(Route Table):
-------------------------- | t | | / \ | | + # | | / \ | | x y | -------------------------- | t/+/x -> node1, node3 | | t/+/y -> node1 | | t/# -> node2 | | t/a -> node3 | --------------------------
订阅(Subscription)与消息派发
客户端的主题订阅(Subscription)关系,只保存在客户端所在节点,用于本节点内派发消息到客户端。
例如client1向主题’t/a’发布消息,消息在节点间的路由与派发流程:
title: Message Route and Deliver client1->node1: Publish[t/a] node1-->node2: Route[t/#] node1-->node3: Route[t/a] node2-->client2: Deliver[t/#] node3-->client3: Deliver[t/a]
假设部署两台服务器 s1.emqtt.io, s2.emqtt.io 上部署集群:
节点名 | 主机名(FQDN) | IP 地址 |
[email protected] 或 [email protected] | s1.emqtt.io | 192.168.0.10 |
[email protected] 或 [email protected] | s2.emqtt.io | 192.168.0.20 |
警告
节点名格式: Name@Host, Host必须是IP地址或FQDN(主机名.域名)
[email protected] 节点设置
emqttd/etc/emq.conf:
node.name = [email protected] 或 node.name = [email protected]
也可通过环境变量:
export [email protected] && ./bin/emqttd start
警告
节点启动加入集群后,节点名称不能变更。
[email protected] 节点设置
emqttd/etc/emq.conf:
node.name = [email protected] 或 node.name = [email protected]
节点加入集群
注意:
EMQ 节点集群使用的 TCP 端口:
4369 集群节点发现端口
6369 集群节点控制通道
集群节点间如有防护墙,需开启上述 TCP 端口互访权限。
启动两台节点后,[email protected] 上执行:
$ ./bin/emqttd_ctl cluster join [email protected] Join the cluster successfully. Cluster status: [{running_nodes,['[email protected]','[email protected]']}]
或,[email protected] 上执行:
$ ./bin/emqttd_ctl cluster join [email protected] Join the cluster successfully. Cluster status: [{running_nodes,['[email protected]','[email protected]']}]
任意节点上查询集群状态:
$ ./bin/emqttd_ctl cluster status Cluster status: [{running_nodes,['[email protected]','[email protected]']}]
节点退出集群
节点退出集群,两种方式:
- leave: 本节点退出集群
- remove: 从集群删除其他节点
[email protected] 主动退出集群:
$ ./bin/emqttd_ctl cluster leave
或 [email protected] 节点上,从集群删除 [email protected] 节点:
$ ./bin/emqttd_ctl cluster remove [email protected]