核心结论

MQTT 是轻量级有状态消息协议;它不是设备模型、存储引擎,也不是完整的物联网平台。

MQTT 为长生命周期客户端连接和通过代理进行的异步消息交换而设计。发布者向某个主题发送消息,代理将该主题与订阅进行匹配,并把消息转发给感兴趣的客户端。发布者不需要知道谁会接收消息,订阅者也不需要知道消息来自何处。

这种解耦非常有用,但它将重要职责转移到了协议契约和代理之中。会话过期、保留消息、遗嘱消息、在途消息限制、主题授权和重连行为都会影响生产环境的实际表现。MQTT 在线路上很精简,但运维好它并不简单。

为什么选择 MQTT

MQTT 适合需要维持外连、发布遥测、接收命令且可能临时断网的设备群。由于连接由设备主动发起,部署时通常不需要在运营商 NAT 或客户防火墙上暴露设备侧监听端口。代理也为大量生产者和消费者提供了一个共享路由节点,避免了每个服务直接调用每个设备。

当同一个事件需要被多个消费者消费时——例如实时运维、规则引擎、数据存储和审计——MQTT 尤其适用。只要主题和载荷契约保持兼容,订阅端可以独立演进,而无需改动发布设备。

MQTT 并不能取代应用 API。设备 provisioning、批量导出、固件分发以及面向用户的请求/响应流程,通常仍然更适合走 HTTPS。

工作原理

客户端建立网络连接(通常基于 TCP + TLS),然后发送 CONNECT 报文。代理接受或拒绝连接,并可能恢复已有会话。发布者发送 PUBLISH 报文,包含主题、载荷、保留标志和 QoS。订阅者注册主题过滤器(可使用 +# 通配符),代理负责匹配。

QoS 是逐跳投递机制:

  • QoS 0:发送一次,不等待 MQTT 层确认。
  • QoS 1:使用确认机制,可能产生重复投递。
  • QoS 2:通过多步交互在 MQTT 协议层避免重复投递。

这些级别都不能证明下游业务动作恰好执行了一次。消费者可能在完成处理后、记录确认前崩溃;同一个真实事件也可能被多次发布。重要消费者仍然需要稳定的事件标识符、幂等处理和明确的结果记录。

保留消息为未来订阅者存储最近一条保留发布,它不是离线任务队列。持久会话可以在客户端断连期间保留订阅和排队消息,但仅限于配置的过期时间和资源上限之内。遗嘱消息让代理在连接意外终止时发布通知,它是有用的信号,但不能作为设备健康状态的确定性诊断。

MQTT 解决的问题

MQTT 提供标准化的消息封装、基于主题的路由、订阅状态管理、投递握手和连接存活性检测。MQTT 5 还增加了更丰富的原因码、会话过期、流控属性、响应主题和用户属性。这些特性可以让故障更可观测,契约更明确。

它适合遥测扇出、异步命令、状态通知、网关到平台的数据交换,以及需要有限会话连续性的间歇性连接客户端。

MQTT 无法解决的问题

MQTT 不定义设备身份生命周期、载荷 Schema、物模型、租户模型、命令授权策略、长期存储格式或业务流程。TLS 可以认证端点并保护流量,但产品仍需处理凭据发放、轮换、吊销、所有权转移和逐主题授权。

代理集群也不是通用的高可用方案。认证服务、DNS、负载均衡器、证书基础设施、存储和下游消费者,都可能在重连风暴中成为瓶颈依赖。

适用场景与不适用场景

当客户端受益于持久外连、异步多对多路由和明确的离线行为时,使用 MQTT。如果环境已有 HTTP 栈且能满足所有需求,或者需要大文件传输,或者涉及硬实时控制回路,MQTT 的吸引力就有限了。工业安全和运动控制需要确定性的本地机制;MQTT 可以报告或协调这些系统,但不应取代其安全层。

相关技术包括 MQTT 代理、TLS、设备身份、主题 ACL、保留状态、设备影子、Sparkplug B 和时序存储。Sparkplug 在 MQTT 之上增加了工业命名空间和生命周期契约。设备影子增加了 MQTT 本身未定义的期望/上报状态语义。

常见误区

“MQTT 保证恰好一次”——混淆了协议投递与业务效果。“MQTT 总是比 HTTP 省带宽”——忽视了连接频率、TLS 握手开销、主题长度、载荷大小和流量特征。“代理就是物联网平台”——忽略了 provisioning、状态管理、规则引擎、数据、运维和产品流程。最后,“已连接等于在线”——忽视了半开连接和过时的应用状态;应使用心跳和领域特定的数据新鲜度规则,而非仅凭连接状态判断。

进入生产环境之前,应先明确主题归属、载荷版本、QoS 选择理由、会话过期策略、队列上限、重连抖动、最大报文大小和反向授权测试,再选择代理实现。