Mosquitto $SYS 主题详解:Broker 自监控指南
结论先行
$SYS 是 Mosquitto 内置的系统主题树,Broker 会定期向这些主题发布自身的运行指标,包括连接数、消息吞吐、字节流量、内存占用等。客户端订阅 $SYS/# 即可获得一份 Broker 的“体检报告”。这些主题默认开启,更新频率由 sys_interval 控制(默认 10 秒)。对于你这种已经跑通认证和 ACL 的环境,只需要给监控账号加上 $SYS 读权限,就能在 MQTTX 或任何 MQTT 客户端里实时观察 Broker 状态。
一、$SYS 是什么,为什么有用
Mosquitto 在运行过程中,会把自己的一些内部统计数据发布到以 $SYS 开头的保留主题上。这不是应用层的业务数据,而是 Broker 自身的运行指标。你可以把它理解为 Broker 的“仪表盘数据”,订阅后就能知道:
- Broker 活着还是快挂了
- 现在有多少客户端连着
- 消息收发速度是快是慢
- 有没有消息因为队列满被丢弃
- 内存用了多少
这些数据不需要额外安装任何监控插件,Mosquitto 启动后就在发布。对于你这种已经跑通认证的环境,用 backend 账号加上 $SYS 读权限,就能直接看到。
二、核心主题分类速查
$SYS 主题很多,但真正日常需要关注的集中在以下几类。
2.1 连接与客户端
| 主题 | 含义 |
|---|---|
$SYS/broker/clients/connected | 当前连接数,最常用的健康指标 |
$SYS/broker/clients/maximum | 历史最高同时连接数 |
$SYS/broker/clients/total | 当前连接 + 已注册但断开的持久客户端总数 |
$SYS/broker/clients/disconnected | 已注册但当前断开的持久客户端数(clean session=false 的客户端) |
clients/connected 是你最应该盯住的指标。如果它突然掉到 0,说明所有设备都掉线了;如果它缓慢下降,说明有设备在悄悄离线。
2.2 消息吞吐(累计)
| 主题 | 含义 |
|---|---|
$SYS/broker/messages/received | Broker 启动以来收到的所有类型消息总数 |
$SYS/broker/messages/sent | Broker 启动以来发出的所有类型消息总数 |
$SYS/broker/publish/messages/received | 仅 PUBLISH 消息的接收总数 |
$SYS/broker/publish/messages/sent | 仅 PUBLISH 消息的发送总数 |
注意 messages/received 统计的是所有 MQTT 报文类型(CONNECT、SUBSCRIBE、PING 等都算),而 publish/messages/received 只统计 PUBLISH。如果你的设备发 PING 很频繁,两个数字会差很多。
2.3 消息吞吐(速率,带时间窗口)
这类主题的末尾是 +,可以替换为 1min、5min 或 15min,表示移动平均速率(每分钟的条数,按指定窗口平均)。
| 主题 | 含义 |
|---|---|
$SYS/broker/load/messages/received/1min | 最近 1 分钟平均每分钟接收消息数 |
$SYS/broker/load/messages/sent/1min | 最近 1 分钟平均每分钟发送消息数 |
$SYS/broker/load/connections/1min | 最近 1 分钟平均每分钟新建连接数 |
$SYS/broker/load/sockets/1min | 最近 1 分钟平均每分钟打开的 socket 连接数 |
速率指标比累计值更有用。累计值只能告诉你“总共发了多少”,速率能告诉你“现在是不是有突发流量”。
2.4 字节流量
| 主题 | 含义 |
|---|---|
$SYS/broker/bytes/received | 启动以来累计接收字节数 |
$SYS/broker/bytes/sent | 启动以来累计发送字节数 |
$SYS/broker/load/bytes/received/1min | 最近 1 分钟平均接收速率(字节/分钟) |
$SYS/broker/load/bytes/sent/1min | 最近 1 分钟平均发送速率 |
2.5 消息积压与丢弃(健康预警)
| 主题 | 含义 |
|---|---|
$SYS/broker/messages/inflight | 已发送但等待确认的 QoS>0 消息数 |
$SYS/broker/publish/messages/dropped | 因 inflight/队列限制被丢弃的 PUBLISH 消息总数 |
$SYS/broker/load/publish/dropped/1min | 最近 1 分钟平均每分钟丢弃数 |
publish/messages/dropped 大于 0 就是警告信号。这意味着有消息因为 max_inflight_messages 或 max_queued_messages 限制被丢掉了。如果你的设备 QoS 用的是 1,丢消息可能意味着客户端处理不过来或者网络太差。
2.6 存储与订阅
| 主题 | 含义 |
|---|---|
$SYS/broker/retained messages/count | 当前保留消息数量 |
$SYS/broker/subscriptions/count | 当前活跃订阅数 |
$SYS/broker/messages/stored | 存储的消息总数(保留消息 + 离线队列) |
retained messages/count 如果一直增长,说明你的设备在不停发布保留消息,可能需要清理策略。
2.7 Broker 自身信息
| 主题 | 含义 |
|---|---|
$SYS/broker/version | Mosquitto 版本字符串(静态,订阅时只发一次) |
$SYS/broker/uptime | 运行秒数 |
$SYS/broker/timestamp | Broker 构建时间(静态) |
$SYS/broker/heap/current | 当前堆内存使用(可能因编译选项不可用) |
$SYS/broker/heap/maximum | 历史最大堆内存 |
$SYS/broker/version 在你排查 CVE 或确认版本时很有用。uptime 结合 clients/connected 可以判断 Broker 是否经历过意外重启。
三、怎么订阅
3.1 在 MQTTX 里
你已经在 MQTTX 里连上了 backend 账号,只需要新建一个订阅:
- Topic:
$SYS/# - QoS:
0
消息列表就会开始刷出 Broker 的各项指标。
注意:# 通配符不会匹配 $SYS 开头的主题。如果你订阅 #,收不到任何 $SYS 数据。必须显式订阅 $SYS/#。
3.2 在命令行
mosquitto_sub -h 127.0.0.1 -p 1883 -u backend -P '你的密码' -t '$SYS/#' -v
-v 会同时打印主题名和值,方便对照。$SYS 在 shell 里有特殊含义(环境变量),必须用单引号包起来,否则会被 shell 展开成空字符串。
3.3 只看关键指标
如果不想被几十个主题刷屏,可以只订阅你关心的:
mosquitto_sub -h 127.0.0.1 -p 1883 -u backend -P '你的密码' \
-t '$SYS/broker/clients/connected' \
-t '$SYS/broker/messages/received' \
-t '$SYS/broker/messages/sent' \
-t '$SYS/broker/publish/messages/dropped' \
-t '$SYS/broker/uptime' -v
四、更新频率:sys_interval
$SYS 主题的更新周期由 mosquitto.conf 中的 sys_interval 控制,默认 10 秒。大多数非静态主题每隔 sys_interval 秒发布一次;version 和 timestamp 这类静态主题只在客户端订阅时发送一次。
你可以调整:
sys_interval 30
设为 30 秒可以减少 Broker 发布 $SYS 的负载。设为 0 则完全关闭 $SYS 发布。对于你的场景(几千台设备、需要监控 Broker 健康),保持默认 10 秒或调到 30 秒都合理。
五、ACL 权限
你之前的 ACL 里给 backend 加了:
user backend
topic read $SYS/#
这是正确的。没有这行权限,$SYS 订阅会被静默拒绝,MQTTX 里看到的就是“订阅了但收不到任何消息”。
生产环境建议单独创建一个监控专用账号,只授予 $SYS 读权限,而不是复用 backend(backend 还有业务主题的读写权限)。这样监控凭证泄露的影响范围更小。
六、哪些指标值得日常盯
对于你的设备监控场景,优先级最高的几个:
| 指标 | 异常信号 |
|---|---|
clients/connected | 突然暴跌 = 大量设备掉线 |
publish/messages/dropped | 非 0 = 有消息被丢弃,检查队列限制 |
messages/inflight | 持续很高 = QoS 确认跟不上,可能网络或客户端处理能力不足 |
load/messages/received/1min | 突增 = 可能有设备在疯狂发消息(死循环或故障) |
retained messages/count | 持续增长 = 保留消息堆积,需要清理策略 |
七、注意事项
$SYS 不会匹配 #。订阅 # 收不到 $SYS 数据,必须显式订阅 $SYS/#。
静态主题只发一次。$SYS/broker/version 和 $SYS/broker/timestamp 标记为静态,客户端订阅时只收到一次,不会周期更新。其他主题按 sys_interval 周期发布。
命令行里的 $ 要转义。用单引号 '$SYS/#' 或 \$SYS/#,否则 shell 会把 $SYS 当环境变量展开。
heap/* 可能不可用。这两个主题是否发布取决于 Mosquitto 的编译选项,官方 Docker 镜像可能没有启用。
总结
$SYS 是 Mosquitto 自带的轻量级监控通道。你不需要额外部署任何东西,只要给账号加上 $SYS/# 读权限,就能在 MQTTX 里实时看到 Broker 的连接数、消息速率、丢弃计数和运行时长。日常盯住 clients/connected、publish/messages/dropped 和 load/messages/received/1min 这几个指标,就能覆盖大部分健康检查需求。更新频率由 sys_interval 控制,默认 10 秒,可以按需调整。