MQTT 在工业现场用了三年,我是越来越“挑剔”了。原因很简单:越是万金油一样的协议,越容易被用错位置。MQTT 作为发布/订阅消息协议,在设备上云、数据采集、告警推送这些环节确实省心,可如果把适用范围想得太大,后期现场返工的成本就会非常难看。这篇文章不讲 MQTT 的基本用法,而是把我在真实项目里反复遇到的四个“不适合”场景摊开来讲,包括它们为什么坑、底层哪里不对、以及我最终用了什么替代设计。
这三年,我做过老旧设备数字化改造,也接触过新建产线全链路设计,还给移动设备和户外作业这类网络不稳定的现场搭过通信系统,基本把 MQTT 的“甜区”和“雷区”都踩了一遍。下面这些内容,更多是选型参考,而不是让你直接照搬结论。
1. 三年现场跑下来,我对 MQTT 的“判断标准”发生了很大变化
1.1 从“能跑就行”到“先判断适不适合”
刚开始做工业物联网项目时,我对 MQTT 的态度几乎可以用膜拜来形容。设备端只要有一个支持 MQTT 的 SDK,配一下 Broker 地址,然后 publish 一条数据就能上云;数据点增删、采集频率调整,都不用像传统组态软件那样去绑定变量。老设备改造时,甚至可以用一个几十块钱的网关做协议转换,把 Modbus RTU 转成 MQTT 往外发。这个阶段的判断标准只有一个:能不能跑通。
项目做得多了,尤其是遇到控制系统抖动、断网丢数据、高并发消息堆积这些问题之后,我意识到判断标准不能只看“能不能跑通”,还要看“在什么约束下能长期稳定跑”。工业现场和互联网最大的区别,是它有很多硬约束:有的设备电池一年才能换一次;有的网络在某个区域就是会断;有的控制周期要求毫秒级且抖动不能超过几十微秒。这些约束叠加在 MQTT 上,结果往往不是协议本身出错,而是架构选型把协议放在了错误的位置。
1.2 三个判断维度:确定性、数据量、网络形态
我现在评审一个新项目,几乎都会先过三个维度。
第一个是确定性。数据时延是否可预测?如果需求是每条指令必须在一两毫秒内到达执行机构,那 MQTT 就已经不适合了。它的底层是 TCP,要经过连接建立、报文确认、Broker 转发和队列排队,任何一个环节的调度波动都会体现在延迟抖动里。第二个是数据量。数据是低频状态量还是连续高频波形?前者适合用消息传递,后者用消息传递就像拿小货车搬沙堆。第三个是网络形态。系统能不能接受中心化 Broker?网络断开时业务能不能自闭环?如果不能,MQTT 的架构优点反而会变成单点风险。
这三个维度正好可以解释我这几年踩坑最深的四个场景:闭环控制回路、连续高频波形、断网自治现场、微型低功耗节点。它们不是 MQTT 唯一的短板,却是工业现场最容易爆发问题的地方。
1.3 “不适合”不等于“不能用”
先说明一下,我这里说的不适合,并不是简单下个禁止令,而是指“使用它的代价会超出收益”。比如硬实时闭环,MQTT 不是不能传控制指令,而是延迟抖动会导致控制质量不稳,付出的代价可能是产品报废甚至设备损坏;再比如极低功耗节点,MQTT 不是不能跑,而是常连接和心跳会大幅缩短电池寿命,维护成本极高。所以在讲下面的场景时,我更多会给出一条判断逻辑和一个替代方案,而不是单纯说“不能用”。
2. 场景一:硬实时闭环控制回路,MQTT 进闭环大概率出事故
2.1 现场遇到的现象:从“功能正常”到“批量位置偏移”
大多数产线都有这样的结构:PLC 直接控制伺服驱动器、变频器和安全继电器,按照固定的扫描周期去读输入、算逻辑、写输出。我在一个改造项目里见过一种设计:PLC 和边缘网关用 MQTT 通信,网关收到上位机任务后,再发指令给一台分拣机构的伺服控制器,相当于把原本应该在 PLC 背板里完成的闭环动作,拉到了 MQTT 这条链路上。
刚开始功能测试一切正常,因为整个链路只有一个点,负载很小。可等到产线扩展到二十个点位,Broker 在同一秒内收到几百条消息时,TCP 缓冲、线程调度和 QoS 确认的叠加效应一起出现。同一个动作的响应时间从 30ms 左右抖到了 300ms 甚至 400ms,直接导致分拣位置超出允许范围。排查机械、排查程序都正常,最后抓包才发现问题出在通信链路:消息时延在动态变化,控制周期被彻底打乱。
2.2 根因不是“慢”,而是“不确定性”
很多人一听这个案例,第一反应是 MQTT 太慢了。其实不对。在局域网内,一条 MQTT 消息从发布到订阅端,通常也就是几毫秒到十几毫秒,对于一般监控完全够用。问题在于,这个时延不是稳定的。
MQTT 底层基于 TCP,TCP 有流量控制和重传机制;上层又有 Broker 的消息队列、线程调度、订阅者匹配逻辑。正常情况下这些开销不大,可一旦系统出现瞬时压力,比如同时有很多设备上报或者网络出现丢包,消息就会排队,时延会突然从 10ms 跳到几百毫秒。对于状态监控,这种抖动最多让曲线看起来不平滑;但对于闭环控制,一个 400ms 的延迟足以让执行机构走到完全错误的位置。
更要命的是,QoS 1 和 QoS 2 的确认与重传机制,本意是保证消息不丢,但在弱网环境下反而会加剧延迟累积。控制指令和数据采集消息一旦排在同一个队列里,谁先谁后完全无法表达,工业控制中最基本的优先级语义在 MQTT 里是缺失的。
2.3 现场更稳的分层做法:MQTT 只负责“说”,不负责“执行”
这个项目返工之后,我们团队形成了一个设计原则:MQTT 只进入信息层,不进入执行层。具体拆成三层来看:
- 执行层:伺服、变频器、安全继电器、气缸这些实际物理动作,由 PLC 或专用运动控制器直接驱动,通信用 EtherCAT、PROFINET 或硬接线 I/O,保证固定周期和确定时延。
- 调度层:产线任务、工单、配方切换这些不要求毫秒级确定的操作,PLC 接收后自己排程。
- 数据层:设备状态采集、告警通知、历史数据上报,这部分用 MQTT,哪怕网络抖动几百毫秒都没关系,因为监控系统不依赖它来动作。
如果是给老旧设备做改造,绕不开 MQTT 下行控制,那就必须在 PLC 侧做一个“指令缓存 + 超时校验”机制。消息可以迟到,但迟到的消息不能覆盖掉当前执行状态;超时没有收到新指令,就按安全策略进入停机或保持状态。这个兜底逻辑,比在 MQTT 层硬调 QoS 更可靠。
3. 场景二:连续高频波形数据,MQTT 消息会先变成“风暴”
3.1 哪些数据属于“连续高频波形”
工业现场有一种数据和普通状态量完全不同,就是连续高频波形。典型代表是振动信号、电机电流波形、压力波动、声学检测,以及设备启停瞬间的暂态过程。它的特点是采样率高,往往是 1kHz 甚至 20kHz 起步;数据量随时间持续增长;分析与判读非常依赖时间顺序。
我在一个设备健康监测项目里,一开始试着把振动传感器数据直接通过 MQTT 上报。单个测点 2kHz 采样,三轴加速度,一秒钟产生约 6000 个原始样本。为了减少消息数量,我们按 1 秒打包成一条消息,再经 JSON 序列化后,单条消息体积到了几十 KB。当时觉得每秒发一条问题不大,可当现场有 20 台设备、每台设备 4 个测点,每秒就是 80 条消息,整体带宽和 Broker 压力马上上来。夜间任务调度高峰时,消息堆积越来越严重,延迟从几秒涨到十几分钟,最后只能临时停掉采集。
3.2 “消息风暴”是怎么产生的:小货车搬沙堆
MQTT 的消息协议对短小的数据优化得非常好,头部开销低、连接复用、主题路由方便。但它并不擅长传递“持续、连续、时序性强”的大体积数据。
每条消息都要走完整的 TCP 和 Broker 路由。消息数越大,单 Broker 需要承担的线程切换、内存分配、队列调度开销就越高。QoS 级别提上去之后,确认和重传带来的额外流量会成倍增加,弱网环境下重传更容易放大问题。还有一个隐藏的问题:消费者的处理速度如果跟不上生产者,Broker 就会在订阅者侧堆积消息,堆得太多时要么触发内存淘汰,要么直接把旧消息丢掉,最终造成波形数据缺段,分析结果直接错误。
我用一组估算数据来说明这个矛盾:单机版 MQTT Broker 在普通服务器上处理 1KB 左右的小消息,每秒上万条通常没有压力;但消息体增大到 100KB 以上时,吞吐量会明显下跌,因为带宽和磁盘 IO 先成了瓶颈。拿小货车去搬沙堆,一车一车效率极低,而且很容易把路堵死。
3.3 我改用的方案:边缘缓存 + 摘要上报
高频波形数据需要的不是“消息转发”,而是“按序落盘、按需取用”。后来我改成了一套混合架构:
- 振动、电流波形这类高频原始数据,在边缘网关本地直接写盘,保存成二进制文件或直接进本地时序数据库,等到网络空闲时按文件传输,而不走 MQTT。
- 边缘端同时做特征提取,比如有效值、峰值、峭度、温度趋势,这些特征量几十字节就能表达,通过 MQTT 实时上报,既快又便宜。
- 只有检测到异常或收到云端指令时,边缘端才把对应时间窗口的波形文件推送到时序库或文件服务接口,供上层做二次分析。
这套方案实施以后,MQTT 消息量从每秒 80 条降到了每 5 秒一条左右,带宽占用下降了不止一个数量级,实时性反而更好。因为告警和特征值走 MQTT,本身就是几毫秒级的事,没必要让原始波形挤在同一条通道里。
4. 场景三:断网自治的流动现场,中心 Broker 反而成了最脆弱的一环
4.1 不是所有工业现场都有“满格网络”
地下矿井、隧道施工、移动天车、户外巡检机器人,这些环境里网络往往时好时坏,甚至可能一段时间完全断连。我在一个移动设备调度项目里就碰到过这种情况,设备在车间内运行,经过金属结构密集区域时网络会短暂断开,持续几秒到几分钟。
第一版方案把所有设备接入同一个 MQTT 域,所有数据汇聚到一个中心 Broker,再由中心端向移动设备下发调度指令。这个设计在测试环境很顺利,一到真实车间就露馅了:移动设备进入断网区域后,收不到任何调度指令,虽然本地 PLC 还能按最后一条指令机械运行,但没有任何安全兜底和自适应逻辑。网络恢复后,积压的任务消息又像洪水一样涌进来,设备端和 Broker 都要花好几分钟才能把队列消化完,期间正常的实时指令反而被堵在后面。
4.2 中心化转发在断网时的逻辑缺陷
MQTT 的模型是“客户端到 Broker,再由 Broker 转发到其他客户端”,客户端之间的通信必须经过 Broker。这个模型天然假设 Broker 始终可用,网络始终连通。
一旦断网,设备端既不能发布也不能订阅,整条链路直接坍塌。为了解决断网补偿,很多团队会在客户端本地维护一个消息队列,等重连后再补报。但客户端本地缓存是“私有且无序”的,断网期间产生的业务逻辑变化,比如执行完一个动作后状态发生了多次跳变,硬要按离线顺序重放,往往会把当前状态覆盖成过期状态。断网越久,缓存越大,恢复后的补投会再次冲击 Broker,形成一次短暂的消息风暴。
更让人头疼的是,如果现场业务要求“断网也能继续执行流程”,MQTT 本身不提供这种语义。命令的优先级、超时作废、重复消息幂等,这些都需要在应用层重新设计,而不是靠 QoS 级别能解决的。
4.3 我最后采用的边缘自治思路
这类项目,我现在不会硬撑中心化 MQTT,而是把“规则执行”放在边缘,让 MQTT 只承担“在线同步”职责。
移动设备本地控制器先维护一份“任务缓存”和“状态机”,断网时按最后有效指令继续执行安全动作,或者自动进入安全停机流程。网络恢复后,设备端先把离线期间的事件日志补传上去,再上报实时状态。上传可以延迟,但绝不能因为上传而阻塞现场执行。如果必须要中心化调度,建议在主 Broker 之外增加一个备节点或双链路切换,关键指令通过冗余路径旁路下发。
这里有一个很实用的判断标准:如果一台设备 30 分钟连不上网,业务还能自闭环,MQTT 才适合做它的通信主干;如果不能自闭环,那么 MQTT 再稳定也解决不了现场的安全风险。我后来几乎所有带移动设备的项目,都会先过一遍这个问题。
5. 场景四:功耗和资源都吃紧的微型传感节点,MQTT 是奢侈品
5.1 那些想“直接用 MQTT”的微型传感器
工业无线传感网里有一类节点,是用电池供电的,比如温湿度记录仪、压力传感器、手持巡检终端。它们可能几个月甚至一年才换一次电池,处理器主频也就几十兆赫兹,内存只有几十 KB。对这种节点,很多团队的第一选择也是 MQTT,原因是 SDK 多、上手快、和云平台对接无缝。
实际做下来会发现,MQTT 基于 TCP,TCP 连接本身的建立和维护就需要消耗资源,而且要保持连接,定时还要发心跳。对本来按“睡眠-唤醒-上报-再睡觉”节奏工作的低功耗设备来说,这是一个很大的负担。我见过一个项目,设计目标是电池供电一年不换,设备始终保持 MQTT 长连接,结果实际运行三个月电池就没电了。原因不复杂:心跳唤醒、TCP 保活和数据上报叠加起来,设备大部分时间都在干活,根本没进入低功耗模式。
5.2 协议栈开销到底贵在哪
用数字来看更直观。一个纯粹的 LoRa 或 NB-IoT 低功耗数据上报节点,绝大多数时间处于睡眠状态,每天只醒几次,每次上报几字节到几十字节,协议开销可以被压缩得非常小。而 MQTT 完整协议栈在 MCU 上往往要占用几 KB 到几十 KB 的 RAM 和 Flash,对 8 位或 16 位单片机来说压力很明显。
如果还叠加 TLS 加密,连接握手、证书解析、会话恢复的消耗会更大。再加上 NB-IoT 这类按数据量计费的接入方式,MQTT 的主题名、报文帧头、TLS 消息都会增加流量消耗。按我实际对比过的项目估算,单位数据成本比纯 UDP 或非 IP 数据上报高数倍到十倍,具体看运营商的计费包。
这不是说低功耗设备永远不要用 MQTT,而是通常需要一个边缘网关替它们做“翻译”:传感器用更轻量的本地协议上报,网关作为 MQTT 客户端再上云。传感器保持自己的省电思路,MQTT 集中在网络侧。
5.3 现场降负载的三种常见做法
第一种:定时上报加休眠。传感器本身不上 MQTT,用低功耗定时器唤醒,通过串口或 CAN 把数据交给网关,网关再组包上线。节点平时完全断电,只有上报瞬间才醒来。
第二种:使用 MQTT 的“临时客户端”模式。传感器在休眠时完全断线,醒来后重新连接、发布、再断开。这种方式比常连接省电得多,代价是实时性变差,因为每次重连都要建立 TCP 连接并重新走认证流程。
第三种:如果数据量极小但必须上云,考虑在平台侧做协议转换。传感器走 NB-IoT 的非 IP 数据上报,平台收到后转成 MQTT 消息继续分发。节点端不用跑 TCP 栈,功耗和内存都大幅下降。
选型时我一般会先把设备端的功耗、内存、带宽预算算一遍,再决定节点是“MQTT 客户端”还是“串口数据源”。一个处理器主频不到几十 MHz、内存不到几十 KB的传感器,我更倾向于让它当数据源,而不是硬塞进 MQTT 协议栈。
6. 用一张“适用性检测表”帮后续项目避雷
6.1 我的快速判断表格
这几年我把现场踩过的坑汇总成了一张表,去做方案评审时先过一遍,能挡住大部分问题:
| 场景特征 | 适合 MQTT 的条件(可接受) | 不适合 MQTT 的预警信号 |
|---|---|---|
| 数据频率 | 低频状态量、事件上报,秒级或更低 | 高频连续采样,音频、振动、高速 IO |
| 控制语义 | 数据监控、告警、可视化、远程运维 | 确定性闭环控制指令 |
| 网络稳定性 | 有稳定网络,短时断网可接受 | 弱网、断网自治,要求秒级恢复 |
| 设备资源 | 网关、PC、高端 PLC,有充足算力 | 电池供电微型传感器,内存有限 |
| 架构要求 | 中心汇聚、多对多、低接入成本 | 点对点、高可靠冗余、无中心自治 |
如果一张表扫下来,预警信号超过两个,我就会认真考虑换一套架构,或者加入边缘前置模块。不是说每条预警信号都绝对致命,而是同时出现多个信号时,MQTT 的优势会被快速抵消。
6.2 选型时最容易踩的四个坑
第一个坑:因为“大家都在用 MQTT”,所以我也要用。这是最危险的从众心理。实际选型要看自己的数据特征、网络条件、设备能力,而不是行业趋势。同事跟我说某个大厂全链路都是 MQTT,那只代表他们解决了配套问题,不等于你也可以直接抄。
第二个坑:以为提升 QoS 就能解决可靠性。QoS 提升的是消息确定性交付,代价是额外的确认流量和处理开销。在弱网下,QoS 2 反而可能让消息堆积和延迟失控,数据补报时更明显。
第三个坑:Broker 高可用等于整个系统高可用。如果设备端没有本地缓存、边缘没有自治能力,Broker 再高可用,断网的那一段依旧是黑洞。Broker 层面的热备解决的是服务器故障,解决不了链路中断。
第四个坑:把“延迟低”等同于“时延确定”。MQTT 常规表现确实快,但 TCP、代理转发、重传决定了时延分布不是稳定的。监控场景可以接受,控制场景不能接受。
6.3 想保留 MQTT 又不想翻车,加一个边缘缓冲层
如果不想推翻现有 MQTT 架构,又想规避风险,可以在架构上多加一个“边缘缓冲层”。所有关键数据先写边缘本地的环形缓存或时序库;边缘一份只做本地执行和本地判断,另一份通过 MQTT 上云;对上云的数据设置优先级,状态告警用 QoS 1 即时投递,波形文件走文件同步,控制指令走独立主题并做超时确认。
这个思路让我在大多数现场都能兼顾实时性和数据汇总。它不会消除前文讲的四个问题,但能把故障半径限制在边缘节点内,不至于一断网就影响整条产线。
7. 写在最后:MQTT 的不擅长,恰好让工业架构更清醒
7.1 三年后我留下的两个核心判断
第一个判断:MQTT 适合做“带外信息总线”,而不是“场内主干”。你可以用它把设备状态、告警、工单、历史数据汇聚到平台,但不该让它承担那些需要毫秒级响应的控制链路。
第二个判断:工业现场的需求和互联网不完全一样。互联网可以接受消息延迟,也愿意围绕 Broker 做高可用;但工业现场很多场景要求“断电还能自己跑一会儿”。这决定了你必须在协议之外建立边缘自治能力,而不是指望某一种协议解决所有问题。
7.2 有人问我该怎么选通信协议,我会怎么答
这几年经常有人问我:该选 MQTT 还是 OPC UA,还是干脆自己写一个传文件的服务?我一般不会直接给答案,而是先让他把指标列出来:数据点位数量、采集频率、实时性要求、网络形态、离线要求、设备资源。把这些约束放上桌面,答案其实很直观。
以我自己的经验,意义不在于哪个协议彻底打败另一个,而是让它们互补。OPC UA 负责现场设备的信息建模,MQTT 负责跨网络的数据流通,文件传输或时序库接口负责高频大包数据。这种组合往往比押注某一个协议更健壮。
7.3 给自己设一条快速否决线
最后分享一个我的土办法:在项目启动前,先写一条否决标准。比如,如果场景里同时出现“毫秒级执行”“高频连续采集”“弱网断网自治”“微功耗节点”这几个关键词中的两个,我就不让 MQTT 作为通信主干,而是转成边缘计算加云端同步的混合架构。
这条线帮我挡掉了至少三个可能在后期才暴露问题的方案。每次做完一个项目,我也会回头修正这条线,因为现场总是会逼你看到新的例外。MQTT 是工业物联网里少有的“普通话”,但它终究不是万能的,承认这一点之后,架构设计反而会清醒很多。