在物联网项目里,我被问过最多的问题就是“MQTT和CoAP到底选哪个”。每次听到这个问题,我都想先说一句:这不是一道二选一的选择题,而是一道“先搞清楚自己系统长什么样,再决定用什么协议”的判断题。MQTT和CoAP都诞生于物联网早期,目的都是解决“设备资源有限、网络质量不稳定”下的通信问题,但设计思路完全走的是两条路。一个像“邮局系统”,所有消息通过中心节点中转,讲究发布订阅、消息可靠;一个像“电话直拨”,设备之间点对点交谈,讲究轻量请求、资源约束。
这篇文章我就把两边的底子都拆开,从协议机制、网络模型、可靠性、安全性、实际落地成本几个维度讲透,最后给出一套可以直接照着做的选型思路。不管你是做智能硬件、工业数据采集,还是云端设备管理平台,这篇都能给你一个相对完整的判断框架。
1. 先搞清楚一件事:这两个协议根本不在同一个赛道
很多人把MQTT和CoAP放在一起对比,是因为它们经常出现在同一个需求文档里,显得像是“竞争对手”。但如果你扒开底层设计去看,会发现它们解决的是不同层次的问题。选型之前,先得理解它们各自的出身和设计哲学。
1.1 MQTT的出身:消息中间件下沉到物联网
MQTT全称Message Queuing Telemetry Transport,最早是1999年IBM为石油管道遥测系统设计的。注意这个背景——石油管道,远程、窄带、链路不稳定、设备无人值守。这种场景下你需要什么?你可能需要把几千个传感器数据源源不断传到中心系统,中心系统可能还要反向下发控制指令。传感器不需要知道数据发给谁,中心系统也不需要逐个维护和每个传感器的连接状态。
所以MQTT从骨子里就是一套“消息分发系统”的思维。它有一个中心节点叫Broker,所有设备都连到Broker上,通过“主题”来标识消息的类别。发送方只管往某个主题发消息,接收方自己对感兴趣的主题做订阅,Broker负责把消息匹配、路由、推送给订阅者。这种模式最大的好处是解耦:发送方和接收方不需要知道彼此存在,不需要建立点对点链路,设备上下线对彼此透明。
这个设计放到今天的物联网里,正好契合了很多平台化需求。一个智能家居App要控制全屋几十个设备,app只需要往某个主题发一条控制指令,对应设备收到后就执行,设备不需要知道app是谁、在哪。反过来,几十个设备上报状态,也是往主题一丢,平台统一订阅就能全部拿到。这种“一对多、松耦合、可扩展”的特征,让MQTT几乎成了云端设备接入事实标准。
1.2 CoAP的出身:为受限节点打造的HTTP替代品
CoAP全称Constrained Application Protocol,是IETF CoRE工作组搞出来的,标准编号RFC 7252。设计目标非常明确:给那些内存只有几十KB、CPU主频只有几十兆赫兹、经常需要电池供电跑好几年的“极受限设备”提供一种类似HTTP的应用层通信方式。
HTTP太胖了,这不用多说。一个完整的HTTP请求头动不动几百字节,还得跑在TCP上,TCP三次握手、四次挥手对睡眠型设备来说简直是噩梦。但物联网设备又不是不需要“请求-响应”这种语义,比如传感器被问“你现在的温度是多少”,设备就需要回答一个“读数”。CoAP就把这一套东西搬到了UDP上,用二进制格式压缩报文,头部只占4个字节,大幅度降低了解析开销和传输流量。
另外CoAP原生支持资源的发现、观察等机制。它像是一个“为了低功耗低资源设备重新设计的HTTP协议”,面向的是设备间直接通信、设备与网关通信这类场景。所以在很多LPWAN网络(如NB-IoT、LoRaWAN)的接入层设计里,CoAP的出现频率很高。
1.3 各自的主战场
一句话总结目前我自己经手的项目里看到的分工:
- MQTT适合中心化物联网平台:设备量大、需要统一管理、需要平台下发控制、需要历史消息回溯、需要与业务系统深度集成。
- CoAP适合设备端互联和受限网络直接采集:节点资源紧张、网络带宽极窄、设备间点对点通信、深度睡眠省电场景。
这两个协议的主战场定位,决定了你在做架构选型时,先看自己的数据流形态,再看设备能力,最后才看协议本身。下面两节我把各自的关键机制拆开,讲清楚选型时必须理解的底层逻辑。
2. MQTT选型必须吃透的四个底层机制
很多初学者对MQTT的理解停留在“发布订阅”四个字上,但真正到选型和部署阶段,有几个机制是绕不开的。这四个机制直接决定了系统架构和运维成本,提前想清楚能省不少后面返工的精力。
2.1 Broker中心化架构:它的价值和它带来的约束
MQTT必须有一个Broker,这是它的立身之本。所有客户端(设备也好、App也好、后端服务也好)都长连接到这个Broker上,消息收发全靠它中转。市面上常见的Broker有开源的Mosquitto、EMQX、VerneMQ,商业的有HiveMQ等,选型本身又是一套学问。
这种中心化架构带来的好处非常直接:消息的路由、过滤、分发逻辑都被收敛到一处,要扩容就加Broker节点,要做权限控制就在Broker层统一做,要审计和监控也方便集中采集数据。你不需要去管两个设备之间怎么互相发现、怎么建立连接,连上Broker就可以了。
但“所有设备都连中心”也意味着两件事。第一,Broker是系统的单点依赖,一旦Broker挂了,所有设备之间即使网络正常也无法通信。第二,设备必须先连上Broker才能收发消息,这个“连接”本身是TCP长连接,对设备端的网络稳定性、心跳保活都有要求。
在实际项目中,我见过不少团队为了省事把Broker部署在云上,然后设备走公网连上来。看起来没什么问题,但设备网络差的时候,TCP连接频繁断开重连,Broker端的连接状态管理压力会非常大。如果设备量大,还需要考虑Broker的集群部署和消息持久化方案。这些都是MQTT选型里要提前计算进去的隐性成本。
2.2 QoS三级到底是怎么“可靠”的
MQTT的QoS(Quality of Service)是选型时经常被拿出来讨论的点。它分三级:
- QoS 0:消息最多发一次,发完不管,可能丢失。
- QoS 1:消息至少发一次,保证送达,但可能重复。
- QoS 2:消息恰好发一次,通过四步握手保证不丢不重。
我见过很多刚接触MQTT的人,第一反应是“那我都用QoS 2不就行了,最可靠”。但在真正的工程里,QoS 2的代价和复杂程度远高于它带来的收益。
QoS 2为什么需要四步握手?因为它要在发送方和接收方之间维护一个完整的去重状态,确保消息只被处理一次。这意味着Broker要为每条消息做状态记录,接收方也要做相应的去重判断。在高吞吐场景下,这个开销会被放大得非常明显。所以实际项目中,绝大部分场景用QoS 1就够了——保证消息送达,重复的问题在业务侧做幂等处理。只有像支付、指令下发这类绝对不能重复执行的操作,才值得考虑QoS 2。
从选型角度看,你要评估的是:我的业务能容忍丢消息吗?能容忍重复处理吗?如果两者都不能,那么你要解决的不仅仅是选QoS几的问题,还需要在应用层做消息幂等和补偿机制,不能把所有可靠性都压在协议上。
2.3 主题树、遗嘱消息、保留消息这些“附加能力”
除了最基本的发布订阅,MQTT还有几个非常实用的机制,选型时不能忽视。
主题(Topic)不是简单的字符串,它是有层级结构的,比如home/room1/temperature和home/room2/temperature。订阅方可以用通配符#和+来做多级匹配。这个能力在实际项目中非常关键,它允许你用一套主题规则把设备分组、按区域路由,也可以做权限控制:比如某个设备只允许往device/001/data这个主题发消息,不允许往device/002/data发。在设计主题树的时候,一定要提前规划好层级含义,因为后期改主题结构比重构数据库还痛苦。
遗嘱消息(Last Will and Testament,LWT)是另一个容易被忽略的功能。设备在连接时可以指定一条遗嘱消息,如果设备异常离线(比如网络断开、断电),Broker会代替它发布这条遗嘱消息。这个机制在做设备在线状态监控时非常有用,等于协议层就帮你实现了“心跳超时通知”的功能。
保留消息(Retained Message)则解决了“新订阅者想拿到最近一次状态”的问题。比如一个温度传感器每次上报完温度,Broker可以保留这个主题的最后一条消息;新的订阅者一订阅,立刻就能拿到最新温度,不用等下一次上报。对智能家居这种需要App打开就看到设备状态的场景,保留消息几乎是标配。
2.4 从选型角度看MQTT的隐藏成本
说了这么多机制,背后其实都有成本。MQTT协议自身的报文头虽然很小(固定头最小2字节),但为了保证长连接的稳定,客户端得定期发送心跳包(PINGREQ),Broker端也要维护海量连接的会话状态。设备越多,Broker的内存和CPU消耗就越明显。
另外,MQTT跑在TCP之上,而TCP在弱网环境下的表现并不好。TCP的拥塞控制、重传机制在丢包率高的网络中会大幅降低吞吐,还会带来“队头阻塞”问题。如果你的设备长期处于信号差、链路抖动的环境,TCP的劣势会被放大。这也是为什么有些团队宁可放弃MQTT的生态,也要在设备端选择基于UDP的CoAP。
我举一个具体的例子:有一个做共享设备的项目,设备用的是4G Cat.1模组,网络信号不稳定,原来用MQTT协议,设备经常出现掉线重连,Broker端同一时间维护的连接数虚高,消息延迟也不稳定。后来把设备端的接入协议换成CoAP,虽然要自己处理可靠重传,但整体通信稳定性和功耗都得到明显改善。这个案例后面讲选型框架时还会提到。
3. CoAP选型必须吃透的三个设计取舍
CoAP的好处不是看一眼文档就能完全感受到的。它的设计非常强调“受限”二字,很多选择都是在资源约束下做出的权衡。理解这一点,你才真正知道CoAP适合什么、不适合什么。
3.1 基于UDP与4字节头部意味着什么
CoAP默认跑在UDP上,默认端口5683,DTLS加密后是5684。整个消息的头部固定为4字节,包含版本、类型、Token长度、代码和消息ID等关键信息。对比一下TCP的握手开销和HTTP的头部体积,差距是非常可观的。
UDP是面向无连接的,没有握手、没有状态维护。对设备来说,这意味着几点:不需要维持一个长连接,用完了就结束,省电;没有TCP的拥塞控制逻辑,发送行为简单直接;可以任意时刻发消息,不用考虑连接是否断开。
但UDP的不可靠性怎么弥补?CoAP设计了两层机制。第一,消息类型区分:CON(Confirmable,需要确认)和NON(Non-confirmable,不需要确认)。CON消息如果没收到ACK,发送方会按指数退避策略重传;NON消息则发完即止。第二,CoAP的可靠传输在应用层做,而不是像TCP那样在内核里做,应用可以根据业务需要控制重传策略。
这里要特别提一个细节:CoAP虽然默认UDP,但也支持通过TCP和WebSocket传输(RFC 8323)。只不过目前实际应用中,绝大多数还是UDP方式,因为背后的核心优势就是省电和低开销。如果改成TCP,这些优势基本就没了。
3.2 请求响应模式与观察模式的使用边界
CoAP的通信模型和HTTP非常像,是标准的请求响应模式。一个CoAP客户端向服务器发一个GET请求(比如coap://device/temperature),服务器回一个响应,带上温度值。这种模式简单直接,适合一问一答的场景,比如上位机查询仪表读数、App查询传感器状态。
但物联网里还有另一种常见的交互:持续订阅某个状态变化。对HTTP来说,只能靠轮询;对MQTT来说,有现成的订阅机制;CoAP对应的方案是观察(Observe)模式,客户端可以“订阅”一个资源,服务器在资源变化时主动推送通知。这里有个比较tricky的点:Observe模式虽然好用,但因为是UDP上的应用层订阅,网络路径上如果存在NAT网关,网关的映射超时可能导致设备收不到通知。后面讲NAT时会专门展开。
你要判断自己的业务里,客户端主要是“主动查”还是“被动等”。如果大量是主动查,CoAP的请求响应模式非常自然,几乎没有额外学习成本。如果是被动等,CoAP的Observe能用,但在公网环境下需要配合其他机制来保活。
3.3 资源发现与受限网络:什么时候CoAP是加分项
CoAP还有一个HTTP没有的设计特性:资源发现(Resource Discovery)。一个CoAP服务器可以通过访问/.well-known/core来列出自己支持的所有资源路径。比如一个传感器节点可能会返回:</sensors/temp>;rt="temperature-c";if="sensor",</sensors/humidity>;rt="humidity-c";if="sensor"。相当于每个设备自带一份“接口文档”,应用层可以动态发现设备能力,而不是靠硬编码的地址表。
这个能力在开源硬件、动态组网场景里非常实用。比如你用开发板搭了一套环境监测系统,新加一个节点,平台不需要预先配置它的接口地址,直接通过资源发现拿它的能力描述即可。
另外CoAP原生适配IPv6和6LoWPAN网络,报文压缩、分片都有对应的规范。对运行在LoRaWAN、NB-IoT这类极窄带网络上的设备,CoAP的报文体积优势是MQTT无法比拟的。实测下来,一个完整的CoAP GET请求加上响应,总字节数往往能控制在几十字节内,这在按流量计费或带宽极有限的环境里完全是碾压性的优势。
4. 一张表看穿关键差异,但别只看表
做选型对比,表格是最直观的。我先把核心差异列出来,然后逐项展开讲那些表格里看不出来的深层影响。
| 对比维度 | MQTT | CoAP |
|---|---|---|
| 传输层 | TCP/TLS,也可跑WebSocket | UDP/DTLS,也可跑TCP/WebSocket |
| 通信模型 | 发布/订阅,Broker中转 | 请求/响应,点对点,可观察 |
| 消息头部 | 固定头最小2字节,实际报文较长 | 固定头4字节,报文紧凑 |
| 可靠性 | QoS 0/1/2 三层语义 | CON/NON + 确认重传 |
| 中心节点 | 必须,Broker | 不需要,可设备直连 |
| 消息路由 | 主题树匹配 | URI资源路径 |
| 设备沉睡 | 长连接前提,耗电较高 | 无连接,适合睡眠唤醒 |
| 服务发现 | 无内建机制,需额外设计 | 内建资源发现 |
| 安全 | TLS(8883端口) | DTLS(5684端口) |
| 典型场景 | 设备接入云端平台、App控制 | 设备间直连、受限网络采集 |
| 生态成熟度 | 极高,Broker、客户端、工具链丰富 | 中等,主要在嵌入式/专网领域 |
4.1 通信模型的分水岭:数据是“推”还是“拉”
上面的表格里,我认为最值得你盯住的是第二行:通信模型。这一行基本决定了八成以上的选型走向。
MQTT是“推”模式。设备把消息推到Broker,Broker再推给订阅者。整个过程消息是主动流转的,发送方不需要等接收方来要。CoAP是“拉”模式,本质上是客户端发起请求,服务器给响应。虽然Observe模式可以做到服务器持续推送,但前提还是客户端先发起订阅请求,而且推送的持续性受网络路径状态影响。
用生活类比:MQTT像订报纸,你订了之后报社每天定时把报纸送上门,不用你去问;CoAP像打电话问天气,你想知道的时候拨个电话问一下,对方告诉你答案。前者适合频繁、持续、多对多的数据流,后者适合低频、按需、一问一答的场景。
所以当你判断自己的业务时,先问一句:消息是设备主动上报给平台,还是平台主动来问设备?如果两者都有,再看哪部分是主量。主量是上报,MQTT更顺手;主量是查询,CoAP更轻便。
4.2 NAT和网络穿透:一个容易被忽视的硬伤
很多设备都部署在家庭路由器、企业防火墙后面,私网IP地址对外不可见。这时候设备能否被平台主动访问,就取决于NAT映射的打通和保持。
MQTT在这件事上的优势来自Broker中心化。设备主动向外发起TCP连接,在NAT设备上建立映射,然后保持这个长连接不退。只要连接不断,平台随时可以通过Broker向设备下发消息,不需要反向穿透。TCP连接本身有状态,NAT设备通常会长期保持这个映射,配合MQTT的心跳包,连接可以稳定维持很长时间。
CoAP就麻烦了。CoAP基于UDP,UDP的NAT映射通常是无状态的,网关设备里的映射条目空闲几十秒到几分钟就可能被回收。设备如果深度睡眠,或者很长时间不发包,平台侧想主动发送CON请求给设备,经常找不到设备——因为NAT映射已经失效了。这个问题在设备部署在运营商级NAT(CGNAT)后面时尤其明显。
所以在公网环境下用CoAP,基本需要自己实现心跳保活机制,或者配合设备主动发起请求的“反向”通信模式。CoAP那套资源发现、观察模式在局域网、专网里很好用,一放到公网就会被NAT问题掣肘。这是选型时最容易被忽略的现实约束。
4.3 安全性选型:TLS和DTLS的实际权衡
两个协议的安全方案也截然不同。MQTT跑TCP,用TLS加密;CoAP跑UDP,用DTLS。两者虽然同源,但工程化现状差别很大。
MQTT加TLS的生态非常成熟:证书签发、双向认证、Broker端TLS终止、负载均衡器SSL卸载,这些东西在互联网基础设施里已经练了二十年,资料和方案一抓一大把。做IoT平台时,设备端烧录CA证书、服务端配置双向认证,这些都是标准操作。
DTLS相对就“原始”很多。它基于UDP实现TLS语义,但UDP的乱序、丢包、重放问题让DTLS在弱网下的握手成功率不如TLS稳定。更麻烦的是,很多现成的CoAP协议栈对DTLS的支持性能一般,在资源受限的MCU上做DTLS握手,内存和CPU开销都不小。还有一点,DTLS使用的PSK(预共享密钥)模式在设备量产时要处理好密钥的分发和更新,如果密钥硬编码到固件里,后期更新密钥就是一场运维噩梦。
安全选型的结论是:如果你的设备需要上公网、需要对接云端平台,TLS+MQTT的组合在工程上最省心;如果你只在私有网络内通信,对安全要求是内部级别,CoAP可以配合DTLS或应用层加密使用。
5. 选型决策框架:遇到具体项目可以照做
前面的机制拆解,都是为了让这一节的决策框架“有据可依”。下面我把自己在实际项目中反复用过的一套判断流程分享出来。你不需要精通两个协议的所有细节,只需要顺着这个流程回答几个关键问题,基本能得出一个不后悔的结论。
5.1 四个能直接问自己的关键问题
在做任何技术选型时,我习惯先画一张最简单的系统拓扑图:设备在哪里,平台在哪里,数据怎么流,控制指令怎么下。然后依次问这四件事:
- 设备能和中心直接保持长连接吗?如果设备部署在用户家庭、野外、移动载体上,网络情况不可控,长期维持长连接的成本高不高?如果维持不了,MQTT的推送优势就发挥不出来。
- 消息的主要方向是什么?设备持续上报数据给平台,还是平台经常主动查询设备状态?前者倾向于MQTT,后者倾向于CoAP。
- 设备资源有多紧张?MCU内存只有几十KB、Flash只有几百KB、用纽扣电池供电?那CoAP的报文体积优势就非常关键;如果设备用的是Linux系统模组,资源充裕,MQTT的生态优势更能发挥作用。
- 系统的维护主体是谁?你是否有能力维护自建的Broker集群?是否愿意自己处理CoAP上的可靠重传和NAT保活?如果团队规模有限,优先选择社区成熟、方案完备的协议,可以省下大量排坑时间。
这四个问题不是孤立回答,而是要交叉起来看。举几个我实际遇到过的典型组合。
5.2 典型场景的选型结论
第一个场景:智能家居设备接云平台。设备是WiFi插座、灯泡、传感器,家中有路由器,云端有控制平台,App需要随时下发开关指令。这时候设备通常可以保持长连接,数据方向既有上报也有下发,设备用的是ESP32这类资源相对充裕的WiFi模组。选MQTT几乎是唯一合理的选择。基于WiFi的TCP长连接稳定可靠,MQTT生态里成熟的Broker和SDK可以省掉大量开发时间。实测下来连上之后,控制指令延迟能做到毫秒级。
第二个场景:农田环境监测。设备是太阳能供电的低功耗传感器,通过LoRaWAN网关上送数据,每隔一小时上报一次土壤墒情。数据方向以上报为主,偶尔的平台配置指令对实时性要求不高,设备长期处于休眠状态。这种场景用CoAP就有明显优势,因为无连接的设计让设备可以发送完就睡,不需要维护长连接,报文体积也小,大大降低了LoRaWAN空口占用时间。
第三个场景:工业数据采集。车间里几十台设备,通过工业网关把PLC、仪表的数据采集上来,再传到工厂的管理平台。工厂内网环境稳定,带宽也够,数据是高频持续上报,同时平台需要对产线做一些启停控制。MQTT非常适合,Broker部署在工厂机房或私有云上,设备接入稳定,而且主题树可以按车间、产线、设备类型做精细化权限管理,方便多角色使用。
第四个场景:车联网信息上报。车辆在移动网络中部署,4G/5G网络状态会不断变化,频繁切换基站会导致TCP连接中断。如果用MQTT,设备会频繁触发重连,Broker端连接管理压力很大。我见过的车联网项目里,也有不少方案在采集链路上采用MQTT,但要么依赖MQTT的自动重连机制,要么在网络层做一些优化。如果是上报低频车辆状态数据到云端,CoAP反而更合适,无连接的特性让它天然不怕基站切换。
5.3 混合部署是常态,别非此即彼
大多数成熟项目的真实情况是:不是整个系统只选一个协议,而是在不同层次用不同协议,通过网关转换实现融合。
典型的分层结构是:感知层设备之间或设备与边缘网关之间用CoAP,网关到云端平台用MQTT。物联设备内部资源有限,和网关距离近,网络稳定,用CoAP可以快速建立通信、低功耗交互;网关是“永远在线”的角色,和云端保持长连接,用MQTT保证云端指令能实时下达到网关。两个协议在网关内部完成转换,各取所长。
还有一种做法:同一设备上同时跑两个协议栈。设备用CoAP供局域网内的其他设备直接发现和查询,同时用MQTT接入云端平台。这种方案适合既要做局域网互联,又要上云的产品。不过对设备资源要求更高,协议栈要维护两套,建议在方案确定前先做一次设备选型评估。
6. 从选型到落地:估算、实测与踩过的坑
再好的选型,落到实际工程里也一定会有计划外的状况。最后一节我分享一些实测经验和踩坑记录,都是常规文档里很少写的内容。
6.1 小细节导致的大问题:内存、报文、心跳
选型时容易忽视的第一个细节是报文体积。MQTT看起来固定头只有2字节,但一个真实的Publish报文要包含主题名、消息体、可能还有报文标识符、属性等。在高频上报场景下,一份完整MQTT报文很容易超过百字节,再加上TCP/IP的头部开销,空口数据量比预想大很多。CoAP同样携带URI路径,但整体还是要紧凑得多。
第二个细节是客户端的内存占用。我用过一个在主流MCU上跑MQTT的开源库,静态配置下缓冲区就占了约8KB RAM,和我的整个业务逻辑内存预算差不多。而一个轻量CoAP实现可以做到远小于这个数字。如果你的设备选型时内存本来就抠得很紧,这个差距可能会直接决定你的MCU要不要升一个档位。
第三个细节是心跳频率。MQTT的Keep Alive机制需要在设计时设置合理的心跳周期,一般建议是业务上能容忍检测到掉线的最长时长的1.5倍。心跳设太短会增加功耗和网络流量,设太长又会导致掉线发现不及时。CoAP本身没有这种长连接保活需求,但如果有NAT映射需要维持,还是得在应用层设计类似的保活包。这里要结合运营商NAT超时时间来做,不同运营商差异挺大。
6.2 踩过的坑:三则真实案例
案例一,某共享设备项目,4G Cat.1模组,开始用了标准的MQTT over TCP方案。没想到这个型号模组的TCP/IP协议栈在弱网环境中表现不佳,基站信号弱时发送缓冲区阻塞,一段时间后TCP连接被Broker断掉,设备进入反复重连的循环。后来把设备端改成嵌入式CoAP,网关侧用Java写了一个简单的协议转换服务,把CoAP请求转成MQTT消息接入平台。改完之后设备重连问题消失了,而且待机功耗明显下降。这个案例给我的教训:用MQTT还是CoAP,要看设备所在网络到底稳不稳定,不能只看平台侧方便。
案例二,一个使用EMQX Broker的物联网平台,设备量到几万台后发现Broker CPU使用率飙升。排查后发现,大量设备设置了过短的心跳周期,且QoS全部用了2。很多设备其实不需要那么高的可靠性,但开发时图省事统一用QoS 2,导致Broker维护了大量会话状态和消息去重数据。把大部分主题降级到QoS 1、心跳周期按实际需求调整后,Broker负载降了一半多。教训:QoS选择要在业务需求和系统开销之间取平衡,越高的QoS不等于越好的系统。
案例三,局域网智能照明系统当场演示故障。设备端用了CoAP,手机App连上局域网直接向设备发控制命令。演示时发现部分设备“失灵”,App发命令没响应。一开始以为是设备固件问题,排查后定位到原因:路由器开启了“AP隔离”功能,局域网内的设备间通信被隔离。CoAP这种点对点通信在这种网络配置下直接失效,而如果走MQTT(设备都连同一个Broker),AP隔离影响就小很多。教训:局域网部署的环境隔离策略,也是选型必须考虑的实际因素。
6.3 本地快速搭建测试环境的方法
选型不能只看文档,强烈建议花半天时间把两边都跑起来,用你自己的业务数据做个简单压测。
MQTT的本地测试非常简单。下载一个Mosquitto,启动之后默认监听1883端口。用命令行工具mosquitto_pub和mosquitto_sub可以快速验证发布订阅流程。想要图形化一点,可以用MQTT X这个客户端工具,支持多主题订阅、报文查看和脚本测试,排查问题非常方便。
CoAP的测试可以用libcoap自带的coap-client,也可以直接用Python的aiocoap库写几行脚本。最简单的验证方式是在本机跑一个coap-server,然后用coap-client发一个GET请求。看报文大小和响应时间,很快就能直观感受到CoAP的轻量特性。
强烈建议在测试环境里同时模拟弱网条件:用网络损伤模拟工具或者直接在路由器上做丢包、限速,然后观察两个协议在相同丢包率下的表现差异。实测丢包率超过一定比例后,TCP上的MQTT会发生明显的拥塞退避和重连,而CoAP的UDP无连接特性反而可能表现得更好。这类实测数据,最后都会成为你向上汇报选型结论时最有说服力的依据。
我从一个共享设备项目的协议切换开始接触到CoAP,当时第一反应也是“为什么不直接用MQTT”,等到真正把设备端报文体积、功耗、弱网表现拉出来对比之后才意识到,物联网协议选型从来没有银弹,只有最合适的方案。希望这篇文章能帮你在做MQTT和CoAP选型时少走一些弯路。如果条件允许,最好把你的真实设备、真实网络环境拿来进行一轮小规模实测,那种踩出来的经验,比任何选型文档都值钱。