3. MQTT Broker可观测性实战
MQTT Broker是IoT平台的消息中枢,它的可观测性直接决定了平台能否在设备规模增长时保持稳定。与通用Web服务不同,Broker的核心健康状态由三类指标刻画:连接维度(当前连接数、连接速率、认证失败数)、主题维度(主题总数、订阅关系数、通配符订阅占比)、消息维度(发布/接收速率、丢弃数、队列积压)。本节以EMQX 5.x为主、Mosquitto为辅,完成从指标暴露到看板与告警的完整闭环。
一、指标暴露:让Broker“开口说话”
EMQX内置Prometheus指标端点,默认监听在18083端口的/api/v5/prometheus/stats路径(需在emqx.conf中确认prometheus.enable = true)。它暴露的指标以emqx_为前缀,例如emqx_connections_count、emqx_topics_count、emqx_messages_publish、emqx_messages_dropped。Mosquitto则通过mosquitto.conf中的sys_interval 10开启$SYS/#主题,用订阅方式读取$SYS/broker/clients/connected、$SYS/broker/messages/received等值。
两种方式的关键差异在于:EMQX是拉取式(Prometheus主动抓取),Mosquitto是推送式(通过MQTT主题发布)。生产环境推荐EMQX + Prometheus + Grafana组合,因为拉取式天然支持多实例聚合与历史存储。下面是一段可直接使用的Prometheus抓取配置示例:
scrape_configs:
- job_name: 'emqx'
metrics_path: '/api/v5/prometheus/stats'
static_configs:
- targets: ['10.0.1.21:18083', '10.0.1.22:18083']
relabel_configs:
- source_labels: [__address__]
target_label: instance
注意:EMQX 5.x的Prometheus端点默认需要认证,若开启dashboard.default_username,需在抓取配置中补充basic_auth。抓取间隔建议设为15s,与告警评估周期保持一致,避免因采样过疏导致速率计算失真。
二、看板搭建:三类核心指标的查询与呈现
Grafana看板不必追求指标数量,而应围绕“连接—主题—消息”三条主线组织。以下PromQL可直接用于面板查询(示例基于EMQX指标命名,实际以/metrics输出为准):
- 当前连接数:
sum(emqx_connections_count),用Stat面板显示总量,用Time series显示趋势。 - 连接速率:
sum(rate(emqx_connections_count[5m])),用于识别设备批量上线或重连风暴。 - 主题总数:
sum(emqx_topics_count),配合sum(emqx_subscriptions_count)观察订阅膨胀。 - 消息发布速率:
sum(rate(emqx_messages_publish[5m])),单位msg/s。 - 消息丢弃速率:
sum(rate(emqx_messages_dropped[5m])),这是最容易被忽视但最危险的指标。
看板布局建议:顶部一行放四个Stat(连接数、主题数、发布速率、丢弃速率),中间放连接数与消息速率的双轴时序图,底部放“丢弃原因分布”饼图(按reason标签聚合)。这样一眼就能判断是“量在涨”还是“质在坏”。
三、异常告警:从“看见”到“被通知”
看板解决的是“人找问题”,告警解决的是“问题找人”。在Prometheus中定义规则文件emqx_alerts.yml,核心是三条:
groups:
- name: emqx_health
rules:
- alert: EmqxConnectionSpike
expr: rate(emqx_connections_count[5m]) > 500
for: 2m
labels:
severity: warning
annotations:
summary: "连接速率突增 {{ $value }} conn/s"
- alert: EmqxMessageDropped
expr: rate(emqx_messages_dropped[5m]) > 0
for: 1m
labels:
severity: critical
annotations:
summary: "消息丢弃速率 {{ $value }} msg/s,检查队列与限流"
- alert: EmqxTopicExplosion
expr: emqx_topics_count > 100000
for: 5m
labels:
severity: warning
annotations:
summary: "主题数 {{ $value }},疑似通配符订阅或设备ID泄漏"
三条规则的判断逻辑各有侧重:连接速率突增通常意味着设备批量重连或认证失败后重试,需结合emqx_authentication_failure一起看;消息丢弃是critical级别,因为一旦丢弃,业务侧可能永远收不到该消息,必须立即检查max_mqueue_len和max_inflight配置;主题数膨胀则往往是设备端把动态ID写进了主题层级,导致订阅关系爆炸,需要从emqx_subscriptions_count按topic标签下钻定位。
quantile_over_time(0.95, emqx_connections_count[7d])观察P95值,再以P95的1.5~2倍作为初始阈值,后续根据误报率调整。四、结果判读与常见陷阱
看板搭好后,如何判断“正常”?一个健康的Broker应满足:连接数曲线平滑、无锯齿状剧烈波动;消息发布速率与订阅速率大致匹配;丢弃速率长期为0;主题数增长与设备数增长呈线性关系。若出现“连接数高但消息速率低”,通常是设备连上后不发数据,需检查设备端心跳与QoS配置;若“主题数持续上涨但设备数不变”,则几乎可以确定是主题命名不规范导致的订阅泄漏。
$SYS指标粒度较粗,且不支持Prometheus原生抓取。若生产环境使用Mosquitto,建议通过mosquitto_sub -t '$SYS/#'将数据桥接到Telegraf或EMQX Edge,再统一进入Prometheus,否则告警能力会大打折扣。最后,把告警接入实际通知渠道:Alertmanager配置webhook_configs指向企业微信或钉钉机器人,并在route中按severity分流——critical走电话+群消息,warning只发群消息。这样,Broker的可观测性才真正从“仪表盘”变成了“值班员的耳朵”。