物联网协议选型最常见的错误,是拿「行业主流」当依据。听到别人说 MQTT 是标配,就全站上 MQTT;听到 NB-IoT 省电,就以为必须配 CoAP。结果要么是电池三个月就没电,要么是服务端下发指令要等设备下次上报。
协议没有优劣,只有匹配。这篇给出一个可执行的判断顺序,然后把 MQTT、CoAP、Modbus、HTTP 四种协议放在同一张表里对比,最后落到四个典型场景上,告诉你每个场景该选什么、为什么、以及要避开哪些参数坑。
先看结论
- ✓协议选型不看「哪个先进」,看四个硬条件:设备是否电池供电、网络是否稳定、要不要服务端主动下发、消息频率多高
- ✓MQTT 的 QoS 2 开销是 QoS 0 的 4 倍以上,除了计费和指令下发,其余全部用 QoS 0
- ✓CoAP 在 NB-IoT 上的省电优势,一半来自 UDP 本身,一半来自运营商对 UDP 的资费策略,不是协议魔法
- ✓工业现场绕不开 Modbus,但 Modbus 的坑不在协议,在每家厂商的寄存器地址表都不一样
一、选型先回答四个问题,顺序不能乱
不要一上来就比协议特性。先按下面这个顺序回答四个问题,答案会直接把可选范围压缩到 1-2 个。
| 顺序 | 问题 | 答案指向 |
|---|---|---|
| 1 | 设备是电池供电还是市电供电? | 电池供电 → 必须考虑休眠和 UDP;市电 → 优先长连接 |
| 2 | 设备在什么网络上?4G/5G、NB-IoT、WiFi、有线以太网、还是现场总线? | NB-IoT → CoAP/LwM2M;现场总线 → Modbus/串口转以太网;以太网/WiFi → MQTT |
| 3 | 要不要服务端主动下发指令(控制类业务)? | 要 → 必须长连接或支持服务端推送;不要 → HTTP 轮询也能用 |
| 4 | 消息频率多高?每秒、每分钟、还是每天? | 高频 → 低开销二进制协议;低频 → HTTP 就够,别过度设计 |
这个顺序的意义在于:它把「技术偏好」排除掉了。真实项目里 80% 的选型错误,是在第 1、2 步就把范围定错了,后面再讨论 QoS 和报文格式都是白费。
很多项目因为「以后可能要控制设备」就选了 MQTT 长连接,但设备是电池供电的传感器,一年只上报几次。结果为了维持长连接,电池寿命从 5 年掉到 8 个月。正确做法是上报走 CoAP 或 HTTP,控制走「设备下次上报时带回指令」,或者对这类设备单独走一路。
二、MQTT:长连接场景的默认答案,但有三个参数必须调对
MQTT 的定位很清晰:设备能维持长连接、需要双向通信、有一定消息频率。它的优势是发布订阅模型天然支持一对多下发,生态成熟(EMQX、Mosquitto、HiveMQ 都有生产级实现),调试工具多。
但默认参数直接用会出问题。三个参数必须按场景调:
QoS 等级:不要全链路 QoS 2
| QoS | 语义 | 握手次数 | 相对开销 | 建议用途 |
|---|---|---|---|---|
| 0 | 最多一次,可能丢 | 1 次(PUBLISH) | 1x | 常规遥测数据、状态上报 |
| 1 | 至少一次,可能重复 | 2 次(PUBLISH + PUBACK) | 约 2x | 告警、需要确认的数据上报 |
| 2 | 恰好一次 | 4 次(PUBLISH + PUBREC + PUBREL + PUBCOMP) | 约 4-5x | 计费、开关控制等不能重复的指令 |
全链路 QoS 2 是最常见的性能杀手。10 万台设备、每秒 1 条消息的场景,QoS 2 会让 Broker 的 CPU 直接翻四倍,而业务上根本不需要——遥测数据丢一条不影响任何判断。合理的做法是按消息类型分级:遥测 QoS 0,告警 QoS 1,控制指令 QoS 1 加业务层幂等。
主题(Topic)设计:不要用设备 ID 做通配符订阅
主题设计直接影响 Broker 的路由性能。推荐结构是「业务域/设备类型/设备 ID/数据类型」,比如 `parking/gateway/GW001/status`。反例是 `device/+/data` 这种在设备层做通配符的订阅——每个消息都要遍历匹配所有订阅,设备量上万后 Broker 的 CPU 会持续高位。
心跳与遗嘱:离线判定的正确姿势
- keepalive 设 60-120 秒。设成 10 秒看起来「检测快」,但 10 万台设备的空心跳就是每秒 1 万条报文,纯浪费。
- 一定要用 LWT(遗嘱消息)。设备异常断线时 Broker 会代发遗嘱,这是最可靠的离线通知方式,比靠心跳超时判断快得多。
- 客户端重连必须做指数退避加随机抖动。否则一次基站切换,几万台设备同时重连,Broker 会被打挂。
三、CoAP:被高估的省电神话,和被低估的部署坑
CoAP 常被描述成「专为物联网设计的轻量协议,比 MQTT 省电」。这个说法对一半。CoAP 基于 UDP,报文头只有 4 字节(MQTT 固定头 2 字节但整体交互更重),确实更轻。但省电的真正来源不是协议本身,而是:
- UDP 无连接,设备可以发完就睡,不需要维持长连接和心跳
- NB-IoT 等蜂窝网络对 UDP 有更好的 PSM/eDRX 支持,能进入深度休眠
- 报文小,单次传输耗电低
换句话说,如果设备是市电供电、走 WiFi,用 CoAP 省的那点电毫无意义,反而失去了 MQTT 的生态和工具链。CoAP 真正的适用场景是:电池供电 + NB-IoT/LoRa + 上报频率低 + 不需要实时下发。
CoAP 用 UDP,很多运营商网络的 NAT 映射会在 30 秒到几分钟内失效。设备如果靠「服务端主动下发」,会发现指令根本到不了设备——因为 NAT 映射早就没了。解决办法是设备定期发心跳维持映射,或者干脆改成「设备上报时捎带取指令」的模式。这一点在实验室里完全测不出来,只有真机上线才会暴露。
另一个现实问题是生态。CoAP 的调试工具、可视化、SDK 成熟度都远不如 MQTT。团队如果没有做过 CoAP 项目,学习和踩坑成本要算进排期。
四、Modbus:工业现场绕不开,坑不在协议在厂商
只要项目涉及工业设备——PLC、电表、变频器、温控器、水泵——几乎一定会碰到 Modbus。它简单到几乎不可能实现错,但实际对接的工作量往往占整个项目的一半。原因只有一个:协议标准只规定了报文格式,没规定寄存器地址。
| 问题 | 实际表现 | 应对方式 |
|---|---|---|
| 寄存器地址不统一 | 同样是温度,A 厂在 40001,B 厂在 30005,C 厂要读 0x0000 偏移 | 每个厂商单独维护一份点位映射表,不要试图通用化 |
| 数据类型不统一 | 同样是 32 位浮点,有的高字在前有的低字在前 | 映射表里标注字节序和字序,逐台验证 |
| 功能码使用不规范 | 标准规定 03 读保持寄存器、04 读输入寄存器,实际常混用 | 以实测为准,文档经常是错的 |
| 轮询延迟累积 | 一台设备 20 个点位,逐个轮询要 2-4 秒 | 合并连续寄存器批量读,一次读 10-20 个地址 |
有一个经验值得说:Modbus 的点位对接,不要相信厂商给的文档,要相信实测。做过一个项目,厂商文档写的寄存器地址全部偏移了 1,导致前期所有数据都读错。正确做法是先读几个已知值的寄存器(比如设备型号、固件版本),确认偏移规则之后再批量配置。
Modbus RTU 和 Modbus TCP 的区别也要注意。RTU 走串口(RS485),需要处理波特率、校验位、从站地址;TCP 走以太网,用 MBAP 报文头替代了 RTU 的校验。转换网关会把 RTU 转成 TCP,但转换过程中经常会丢失从站地址信息,导致多台设备挂在同一个网关下时分不清谁是谁。
五、HTTP 与 WebSocket:什么时候该用,什么时候是过度设计
HTTP 在物联网里被严重低估。如果设备是市电供电、消息频率低于每分钟一次、不需要服务端主动下发,HTTP 是最省事的选择:调试简单(浏览器就能测)、穿透性好(就是普通网页请求)、服务端改起来快。
但有两种情况 HTTP 会变成灾难:
- 设备要实时接收指令。HTTP 只能靠轮询,轮询间隔短了浪费带宽和电量,间隔长了指令延迟不可接受。
- 上报频率高(每秒一次以上)。每次请求都要建连、带一堆 header,开销远超有效数据。这时候 MQTT 的优势才真正体现。
WebSocket 是折中方案:既有 HTTP 的握手和穿透性,又能保持长连接双向通信。适合「Web 端需要实时数据」的场景,比如后台大屏要实时刷新设备状态。但设备端很少用 WebSocket,因为它的报文是文本帧、开销比 MQTT 大,且重连逻辑要自己写。
六、四种协议 12 维对比表
把前面几节收拢成一张表。注意「适合场景」这一列比任何参数都重要——参数只是支撑结论,不能替代结论。
| 维度 | MQTT | CoAP | Modbus | HTTP |
|---|---|---|---|---|
| 传输层 | TCP | UDP | 串口 / TCP | TCP |
| 通信模式 | 发布订阅 | 请求响应 + 观察 | 主从轮询 | 请求响应 |
| 最小报文开销 | 2 字节固定头 + 主题 | 4 字节头 | 8 字节左右 | 数百字节 header |
| 服务端主动下发 | 原生支持 | 支持(观察模式),受 NAT 限制 | 不支持,需轮询 | 不支持,需轮询 |
| 功耗(电池场景) | 中(需维持连接) | 低(可深度休眠) | 不适用(有线供电) | 中高(每次建连) |
| QoS / 可靠性机制 | QoS 0/1/2 | CON/NON 消息 + 重传 | CRC 校验,无重传 | TCP 保证,应用层重试 |
| NAT / 防火墙穿透 | 好 | 差(UDP 映射易失效) | 差(需固定 IP 或端口映射) | 最好 |
| 生态与工具成熟度 | 很高 | 中 | 高(工业领域) | 极高 |
| 调试难度 | 低(有现成客户端) | 中 | 中(需串口工具) | 极低 |
| 典型设备规模 | 1 万 - 100 万 | 1 万 - 50 万 | 单点几十到几百 | 几百 - 几万 |
| 最适合场景 | 双向通信、控制类业务、中高频上报 | 电池供电、NB-IoT、低频上报 | 工业设备、电表、PLC 接入 | 低频上报、第三方系统对接 |
| 最不适合场景 | 电池设备、极低频上报 | 需实时下发、WiFi 环境 | 跨广域网、多站点 | 高频上报、实时控制 |
七、真实项目里,协议从来不是单选
除了极少数单一品类的项目,实际项目几乎都是混合协议。典型结构是:现场设备走 Modbus/串口,本地网关做协议转换和聚合,网关用 MQTT 上云,第三方系统用 HTTP 对接,Web 端用 WebSocket 拿实时数据。
这种结构里,网关是整个方案的枢纽,也是最容易出问题的地方。三个设计要点:
- 1网关要能做协议转换的配置化。每接一个新厂商的设备就要改代码,项目永远做不完。点位映射表应该是配置文件或数据库记录,不是硬编码。
- 2网关要能缓存。上云链路断了,本地数据不能丢,至少缓存 24 小时。这个能力在验收时经常被忽略,出问题时才发现数据断了三天。
- 3网关要能远程升级和远程诊断。现场几十上百个站点,每个都派人去,运维成本会失控。
不要为了「技术先进性」引入第二种协议。每多一种协议,就多一套 SDK、一套调试工具、一套运维流程、一批要培训的人。能用一种解决的场景,绝不要用两种。
八、常见问题
MQTT 和 CoAP 到底哪个更省电?
在电池供电 + 蜂窝网络(NB-IoT)的场景下,CoAP 通常更省电,因为它不需要维持长连接和心跳,可以长时间深度休眠。但差距没有传说中那么大——实测区间通常在 20%-40%,取决于上报频率和网络制式。如果是市电供电,这个差异没有意义。
一个平台能不能同时支持多种协议?
能,而且这是标准做法。架构上把「接入适配层」独立出来,每种协议一个适配器,统一转换成内部消息格式后进入平台核心。EMQX 这类 Broker 支持 MQTT/CoAP/LwM2M 多协议接入,Modbus 一般通过网关转换。关键是内部数据模型要统一,否则每接一种协议就要改一次业务代码。
Modbus 能不能直接上云?
技术上可以(有 Modbus TCP over Internet 的方案),但强烈不建议。Modbus 没有认证、没有加密、没有重传机制,直接暴露在公网等于把控制权交给任何人。正确做法是用本地网关做 Modbus 采集,网关用 MQTT over TLS 上云。
设备数量少(几百台)需要专门选协议吗?
几百台的规模,选型对性能几乎没有影响,优先选团队最熟悉的。如果团队只写过 HTTP 接口,就用 HTTP 轮询,别为了「规范」硬上 MQTT。等设备量上来再迁移,几百台的改造成本完全可控。
常见问题
选型和技术评审时最常被问到的几个问题,直接给结论。