序言
在智能物联时代,存设备需要联网上云场景。EMQX在此场景中属于设备连接网关关键节点,EMQX不紧紧只是消息中间件的作用,我们更需要监控哪些设备什么时候连接上线,又在什么时候断开下线。
为什么需要感知设备上下线
感知设备上下线在多个场景中都是非常重要的,以下是几个主要原因:
- 设备监控与管理:感知设备上下线可以帮助管理者实时了解设备的状态,从而进行更有效的设备监控和管理。例如,在网络环境中,感知设备是否在线可以确保网络连接的稳定性和安全性。
- 故障诊断与预防:通过感知设备上下线,可以及时发现设备故障或异常状态。当设备频繁上下线或长时间离线时,可能意味着设备存在问题,需要进行检修或更换。这有助于预防设备故障,提高设备的可靠性和稳定性。
- 资源优化:感知设备上下线可以帮助管理者了解设备的使用情况,从而进行资源优化。例如,在云计算环境中,感知设备是否在线可以帮助管理者合理分配计算资源,避免资源浪费。
- 安全控制:在某些场景中,感知设备上下线也是实现安全控制的重要手段。例如,在物联网应用中,通过感知设备是否在线,可以控制对设备的访问和授权,防止未授权的设备接入网络或访问敏感数据。
- 业务连续性保障:在一些需要连续运行或高可用的业务场景中,感知设备上下线可以确保业务的连续性和稳定性。例如,在金融服务或医疗保健等领域,设备的稳定运行对于业务的正常进行至关重要。通过感知设备上下线,可以及时发现并处理设备故障或异常状态,确保业务的连续性和稳定性。
EMQX如何感知设备上下线?
EMQX感知设备上下线的方法主要依赖于MQTT协议提供的系统主题。在MQTT协议中,当设备客户端连接或断开与EMQX服务器的连接时,EMQX会发布相应的上下线事件到特定的系统主题。
具体实现步骤如下:
- 配置EMQX的ACL规则:EMQX默认可能只允许本机的MQTT客户端订阅_SYS_系统主题。因此,你需要修改_EMQX_的_ACL_(访问控制列表)规则,允许其他客户端订阅与设备上下线相关的系统主题。例如,你可以添加一条规则允许所有客户端订阅
$SYS/brokers/+/clients/#
这样的主题。 - 创建MQTT客户端:使用MQTT客户端库(如Paho MQTT、MQTT.js等)创建一个MQTT客户端,并连接到EMQX服务器。
- 订阅系统主题:在MQTT客户端中,订阅与设备上下线相关的系统主题。例如,你可以订阅
$SYS/brokers/${node}/clients/${clientid}/connected
以感知设备的上线事件,订阅$SYS/brokers/${node}/clients/${clientid}/disconnected
以感知设备的下线事件。其中 n o d e 是 E M Q X 节点的标识符, {node}是EMQX节点的标识符, node是EMQX节点的标识符,{clientid}是设备的客户端ID。
EMQX系统主题
EMQX 周期性发布自身运行状态、消息统计、客户端上下线事件到以 $SYS/
开头系统主题。$SYS
主题路径以 $SYS/brokers/{node}/
开头。{node} 是指产生该 事件 / 消息 所在的节点名称。
EMQX 中$SYS
主题中绝大部分数据都可以通过其他更耦合性更低的方式获取, 设备上下线状态可通过规则引擎获取。
客户端上下线事件
$SYS
主题前缀:$SYS/brokers/${node}/clients/
本事件默认为开启状态,关闭请参照sys_topics.sys_event_messages。
主题 (Topic) | 说明 |
---|---|
${clientid}/connected | 上线事件。当任意客户端上线时,EMQX 就会发布该主题的消息 |
${clientid}/disconnected | 下线事件。当任意客户端下线时,EMQX 就会发布该主题的消息 |
connected 事件消息的 Payload 解析成 JSON 格式如下:
{
"username": "foo",
"ts": 1625572213873,
"sockport": 1883,
"proto_ver": 4,
"proto_name": "MQTT",
"keepalive": 60,
"ipaddress": "127.0.0.1",
"expiry_interval": 0,
"connected_at": 1625572213873,
"connack": 0,
"clientid": "emqtt-8348fe27a87976ad4db3",
"clean_start": true
}
disconnected 事件消息的 Payload 解析成 JSON 格式如下:
{
"username": "foo",
"ts": 1625572213873,
"sockport": 1883,
"reason": "tcp_closed",
"proto_ver": 4,
"proto_name": "MQTT",
"ipaddress": "127.0.0.1",
"disconnected_at": 1625572213873,
"clientid": "emqtt-8348fe27a87976ad4db3"
}
客户端监听系统事件授权
客户端订阅 $SYS
主题,需要在 ACL File 配置 ACL 规则。
文件格式
基于文件的授权权限列表简单轻量,适合配置通用的规则。对于上百条或者更面向客户端的规则,推荐使用其他授权来源。基于文件的权限列表可以作为防护置于授权链末端。
基于文件进行授权检查前,您需要将授权规则以 Erlang 元组 数据列表的形式存储在文件中。
基本语法和概念如下:
- 元组是用花括号包起来的一个列表,各个元素用逗号分隔
- 每条规则应以 . 结尾
- 注释行以 %% 开头,在解析过程中会被丢弃
代码示例:
%% 允许用户名是 dashboard 的客户端订阅 "$SYS/#" 这个主题
{allow, {user, "dashboard"}, subscribe, ["$SYS/#"]}.
%% 允许来自127.0.0.1 的用户发布和订阅 "$SYS/#" 以及 "#"
{allow, {ipaddr, "127.0.0.1"}, all, ["$SYS/#", "#"]}.
%% 拒绝其他所有用户订阅 "$SYS/#" 和 "#" 主题
{deny, all, subscribe, ["$SYS/#", {eq, "#"}]}.
%% 如果前面的规则都没有匹配到,则允许所有操作
{allow, all}.
在每个元组中:
第一个元素表示该条规则对应的权限;可选值:
- allow (允许)
- deny(拒绝)
第二个元素用来指定适用此条规则的客户端,比如:
- {username, “dashboard”}:用户名为 dashboard 的客户端;也可写作{user, “dashboard”}
- {username, {re, “^dash”}}:用户名匹配 正则表达式 ^dash 的客户端
- {clientid, “dashboard”}:客户端 ID 为 dashboard 的客户端,也可写作{client, “dashboard”}
- {clientid, {re, “^dash”}}:客户端 ID 匹配 正则表达式 ^dash 的客户端
- {ipaddr, “127.0.0.1”}:源地址为 127.0.0.1 的客户端;支持 CIDR 地址格式。注意:如果 EMQX 部署在负载均衡器后侧,建议为 EMQX 的监听器开启 proxy_protocol 配置 ,否则 EMQX 可能会使用负载均衡器的源地址。
- {ipaddrs, [“127.0.0.1”, …, ]}:来自多个源地址的客户端,不同 IP 地址之间以 , 区分
- all:匹配所有客户端
- {‘and’, [Spec1, Spec2, …]} :满足列表中所有规范的客户端。
- {‘or’, [Spec1, Spec2, …]} :满足列表中任何规范的客户端。
第三个元素用来指定该条规则对应的操作:
- publish:发布消息
- subscribe:订阅主题
- all:发布消息和订阅主题
- 从 v5.1.1 版本开始,EMQX 支持检查发布与订阅操作中的 QoS 与保留消息标志位,您可以在第三个元素中加上 qos 或 retain 来指定检查的 QoS 或保留消息标志位,例如:
- {publish, [{qos, 1}, {retain, false}]}:拒绝发布 QoS 为 1 的保留消息
- {publish, {retain, true}}:拒绝发布保留消息
- {subscribe, {qos, 2}}:拒绝以 QoS2 订阅主题
第四个元素用于指定当前规则适用的 MQTT 主题,支持通配符(主题过滤器),可以使用主题占位符:
- “t/${clientid}”:使用了主题占位符,当客户端 ID 为 emqx_c 的客户端触发检查时,将精确匹配 t/emqx_c 主题
- “
$SYS/#
”:通过通配符匹配$SYS/
开头的所有主题,如$SYS/foo、 $SYS/foo/bar
- {eq, “foo/#”}:精确匹配 foo/# 主题,主题 foo/bar 将无法匹配,此处 eq 表示全等比较(equal)
另外还有 2 种特殊的规则,通常会用在 ACL 文件的末尾作为默认规则使用。
- {allow, all}:允许所有请求
- {deny, all}:拒绝所有请求
通过 Dashboard 配置
在 EMQX Dashboard 页面,点击左侧导航目录的 访问控制 -> 授权 进入授权页面。
EMQX 已默认配置了基于文件的授权检查器。您可点击 File 数据源对应的操作栏下的 设置 按钮查看或更改 ACL 文件中配置的授权规则。
在 授权页面,单击创建,选择数据源为 File,点击下一步,进入配置参数页签:{allow, {user, "clientdevice"}, subscribe, ["$SYS/#"]}.
clientdevice:客户端名字
如何监听EMQX系统主题
监听系统主题授权
在ACL file配置{allow, {user, "clientdevice"}, subscribe, ["$SYS/#"]}.
订阅主题
上线事件topic | $SYS/brokers/${node}/clients/${clientid}/connected |
---|---|
下线事件topic | $SYS/brokers/${node}/clients/${clientid}/disconnected |
根据EMQX通配符 | $SYS/brokers/+/clients/# |
如果需要实现共享模式 | $share/device_service/$SYS/brokers/+/clients/# |
(在共享订阅模式下,多个客户端可以组成一个共享组(Shared Group),共同订阅一个主题(Topic)。当消息发布到这个主题时,EMQX会按照特定的分发策略(如随机、轮询、粘性、哈希等)将消息分发给共享组中的一个客户端,确保每个消息只被一个客户端接收并处理。)
emqx系列文章
MQTT BROKER 技术选型
Windows安装EMQX
EMQX 快速入门
EMQX 实践