MQTT 是一种轻量级的发布/订阅消息协议,如今已成为将现场数据从车间设备上传至仪表盘、历史数据库与 SCADA 系统的默认传输方式。它无需每个客户端轮询每台设备,而是由传感器与网关将读数发布到中央代理(broker)上的命名主题(topic),再由任意数量的消费者订阅它们关心的主题。这种解耦特性,加上可调的投递保证与极小的报文开销,正是 MQTT 3.1.1 与 MQTT 5.0 成为工业物联网(IIoT)架构标准的原因。

代理与客户端模型

MQTT 恰好只有两种角色。代理(Mosquitto、EMQX、HiveMQ 或某种云服务)是中央消息路由器。客户端则是其余一切:Modbus 转 MQTT 网关、内置原生 MQTT 协议栈的 PLC、SCADA 节点、历史数据库或移动端仪表盘。客户端之间从不直接通信,只与代理建立一条 TCP 连接,然后进行发布与订阅。代理会将每条发布的消息与所有已连接客户端的订阅过滤条件进行匹配,并相应地转发副本。

正是这种星形拓扑让 MQTT 得以扩展。新增一个仪表盘无需触碰任何一台现场设备,新客户端只需订阅相关主题,由代理负责扇出分发。在典型的 SURIOTA 部署中,一台 SRT-MGATE-1210 Modbus 转 MQTT 网关从电表与传感器读取 RS-485 寄存器,再将每个数值重新发布为 MQTT 消息,从而把传统串口设备变成网络上的发布者。

设计主题层级

主题是以正斜杠分级的 UTF-8 字符串,例如 plant1/utilities/line3/meter07/power_kw。它没有中央化的模式(schema),层级结构是由你自行定义的约定,因此尽早设计正确可以省去日后痛苦的迁移。一套稳健的 IIoT 方案应从宽泛到具体逐级细化:site / area / line / device / metric(站点 / 区域 / 产线 / 设备 / 指标)。

层级名保持小写、避免空格,且切勿使用前导斜杠(首级为空虽然合法但浪费)。不要把会变化的数值(例如设定点)编码进主题名本身;主题用于标识一条消息是什么,数值则由载荷(payload)承载。许多团队会采用 Sparkplug B 规范,正是出于这一原因,它在 MQTT 之上标准化了主题命名空间(group/edge_node/device)与载荷编码。

用于订阅的通配符

发布者始终使用完全指定的主题。订阅者则可使用两种通配符。单级通配符 + 精确匹配一个层级:plant1/+/+/+/power_kw 会返回工厂中每台设备的功率。多级通配符 # 匹配某点以下的所有内容,且必须作为最后一个字符:plant1/utilities/# 会投递公用工程区域的每一项指标。一个 SCADA 历史数据库可能订阅 plant1/# 以采集全部数据,而单屏仪表盘只订阅它需要渲染的那几个主题。

服务质量(QoS):QoS 0、1 与 2

QoS 为每条发布的消息与每个订阅设定投递保证。它在发布端与订阅端独立选择;投递给某订阅者的实际生效 QoS 取两者中的较低值。其权衡在于可靠性与延迟、带宽及代理负载之间。

QoS 名称 握手 投递保证 是否可能重复? 最适用于
0 至多一次 PUBLISH(发完即弃) 无;链路中断时消息可能丢失 高频率、非关键的遥测数据,且下一个采样很快到来(温度趋势、振动数据流)
1 至少一次 PUBLISH 后 PUBACK 保证投递,但可能不止一次到达 是;消费者必须是幂等的 大多数 SCADA 标签更新、电能计数器、重复无害的告警
2 恰好一次 PUBLISH、PUBREC、PUBREL、PUBCOMP(四次握手) 保证恰好投递一次 关键命令、计费级电表读数、不可重复计数的累加器

实用建议:不要把所有内容都默认设为 QoS 2。四次消息握手大致会使每条消息的代理流量翻两番,并增加往返延迟,这在受限的蜂窝或 LoRa 回程链路上影响很大。对于大多数工厂遥测,配合幂等消费者的 QoS 1 是最佳折中。把 QoS 2 留给控制写入,以及真正需要恰好一次语义的计数器,例如向计费系统供数的计费级 Modbus 电能表

保留消息

默认情况下,订阅者只会接收它连接之后发布的消息。如果像 plant1/utilities/line3/pump_p101/status 这样缓慢变化的主题只在状态实际改变时才发布,那么班中才连接的仪表盘在下一次变化之前将什么都显示不出来。设置 retain 保留标志会告诉代理存储该主题上的最后一条消息,并立即投递给任何新订阅者。每个主题恰好只有一条保留消息;每次新的保留发布都会覆盖上一条。要清除它,可发布一条带保留标志的零长度载荷。

对最近已知状态值(设备状态、设定点、配置)使用保留消息,这样任何新客户端都能立即获得一份快照。不要对高频流式遥测使用保留,否则新订阅者会收到一个看似当前实则陈旧的读数。

遗嘱(LWT)与保活

客户端连接时可注册一条遗嘱消息(Last Will and Testament,LWT):包含主题、载荷与 QoS,一旦该客户端非正常断开,代理便会自动发布它。一台网关可以在 plant1/utilities/gateway01/state 上设置 offline 的 LWT,并在自身连接时发布(保留的)online。这样任何消费者都能一眼判断网关是否在线,这对于可信赖的 SCADA 状态至关重要。

代理通过连接时协商的保活(keepalive)间隔来检测失联客户端。如果在 1.5 倍保活周期内没有任何报文(哪怕是 PINGREQ)到达,代理便认定客户端已失联并触发其 LWT。常见设置为 60 秒,约 90 秒后即可判定客户端离线。较短的保活能更快检测故障,但会增加空闲的心跳流量,这在按量计费的链路上影响显著。

安全:TLS 与身份认证

MQTT 默认在 1883 端口上运行于明文 TCP 之上,会以明文发送凭据与载荷。对于任何生产环境的 IIoT 系统,都应在 8883 端口上通过 TLS 运行 MQTT。这会加密信道,并借助客户端证书(双向 TLS)以密码学方式认证每台设备。至少应启用用户名与密码认证,并在代理上禁用匿名访问。再叠加主题级访问控制列表(ACL),使某台网关只能在自己的 site/area 分支下发布,而无法订阅它本不应读取的控制主题。纵深防御(用 TLS 保护信道、用凭据或证书确立身份、用 ACL 实施授权)能防止单台被攻陷的设备将整个工厂暴露出来。

MQTT 与 OPC-UA 对比

MQTT 与 OPC-UA 常被拿来比较,但它们解决的是不同的问题。MQTT 是一种传输与消息模式:轻量、以代理为中心,非常适合在不可靠的 WAN 链路上进行多对多遥测,但它本身不携带数据模型,因此含义存在于你的主题约定中,或像 Sparkplug B 这样的覆盖层里。OPC-UA 则是一个完整的信息建模框架,具备带类型的节点、可浏览的地址空间与丰富的安全机制,传统上采用客户端/服务器模式且报文开销更重。两者正日益共存:OPC-UA 在工厂内部定义语义模型,而 MQTT(或基于 MQTT 的 OPC-UA PubSub)负责高效的云端传输。对于供分析使用的全新 IIoT 数据采集,MQTT 加一套清晰的命名空间通常是更快的路径;若深度互操作性与各自动化厂商之间标准化的类型定义是首要诉求,则应选择 OPC-UA。

常见问题

MQTT 对工业控制而言足够安全吗?

协议本身没有强制性的安全机制,因此安全由你负责。配合 8883 端口上的 TLS、客户端证书或强凭据、代理 ACL 以及经过加固的代理,MQTT 适用于工业遥测与监控控制。生产环境中应避免使用明文 1883 端口与匿名访问。

SCADA 标签应该用 QoS 1 还是 QoS 2?

对于绝大多数标签更新使用 QoS 1,并让消费者具备幂等性,使偶尔的重复无害。把 QoS 2 留给控制命令与精确计数器(如计费级电能总量),在那些场景下重复投递会破坏结果。QoS 2 的代理流量与延迟成本要高得多。

MQTT 与 Modbus 轮询架构相比如何?

Modbus 是请求/响应、由主站驱动的;SCADA 主站必须按固定周期轮询每个从站。MQTT 则是按例外报告、由发布者驱动的,因此设备仅在数值变化时或按选定间隔发送数据,从而降低带宽并提升可扩展性。实践中,一台 Modbus 转 MQTT 网关架起两个世界之间的桥梁,在本地轮询串口设备并将结果向上游发布。

使用 MQTT 是否需要边缘设备?

并非总是需要,但确有帮助。原生支持 MQTT 的 PLC 可以直接发布,然而大多数既有设备使用 Modbus 或其他现场总线,因此需要一台边缘网关来转换并缓冲数据。关于这部分逻辑应当归属何处,我们在 边缘网关、PLC 与 RTU 对比中作了说明,而发布出的数据随后会供给仪表盘与 AI 工业分析

MQTT 会回报你在前期做出的若干正确决策:一套清晰的 site/area/line/device/metric 命名空间、按主题而非全局选择的 QoS、用于状态的最近已知值保留消息、为每台网关设置的 LWT,以及从第一天起就启用的 TLS 与 ACL。把这些做对,你就拥有了一条可从单条产线扩展到整座工厂的遥测主干。要了解这如何融入完整的系统架构,请探索 SURIOTA 的物联网服务。