4、OTA更新协议与架构:MQTT/CoAP/HTTP协议对比、更新服务器架构、断点续传与差分更新
OTA(Over-the-Air)更新,说白了就是给设备“打补丁”。但物联网设备不像手机,它们可能只有几百KB内存,网络时断时续,甚至还在用电池供电。选错协议或架构,更新就是一场灾难。
我个人习惯把OTA更新拆成两个层面看:传输协议和服务器架构。协议决定数据怎么传,架构决定系统怎么扛。下面我们一个一个聊。
4.1 三大传输协议对比:MQTT vs CoAP vs HTTP
先看一张对比表,心里有个底:
| 特性 | MQTT | CoAP | HTTP |
|---|---|---|---|
| 传输层 | TCP(长连接) | UDP(支持可靠传输) | TCP(短连接为主) |
| 消息模型 | 发布/订阅 | 请求/响应 + 观察 | 请求/响应 |
| 头部开销 | 2字节最小 | 4字节最小 | 数百字节 |
| QoS支持 | 0/1/2三级 | CON/NON/ACK/RST | 无原生QoS |
| 适用场景 | 低带宽、不可靠网络 | 极低功耗、受限节点 | 宽带、高算力设备 |
| 安全扩展 | TLS + 用户名/密码 | DTLS + 预共享密钥 | TLS + 证书 |
4.2 MQTT:我最常用的协议
MQTT是我在项目中用得最多的协议。为什么?因为它天生为“不可靠网络”设计。
发布/订阅模型让服务器不用知道每个设备在哪。设备上线后订阅一个更新主题,服务器往主题里发一条消息,所有设备都能收到。这在批量更新时特别爽。
QoS(服务质量)是MQTT的杀手锏。我建议OTA更新至少用QoS 1:
- QoS 0:最多发一次,丢了不重传。适合心跳,不适合固件。
- QoS 1:至少发一次,可能重复。配合固件校验,够用。
- QoS 2:恰好发一次,开销大。我一般不用,除非合规要求。
4.3 CoAP:受限设备的首选
CoAP跑在UDP上,头部只有4字节。你想想看,一个内存只有32KB的传感器,跑HTTP简直是奢望。CoAP就是为这种场景生的。
CoAP的观察模式很有意思。设备可以“订阅”一个资源,服务器有更新时主动推送。这和MQTT的发布/订阅有点像,但更轻量。
不过要注意,CoAP的可靠传输靠的是CON(确认消息)和重传。我在一个项目中遇到过,设备在弱网环境下反复重传CON消息,把电池耗光了。后来我们加了指数退避,问题才解决。
4.4 HTTP:简单但“重”
HTTP的优势是简单。设备发一个GET请求,服务器返回固件。但它的头部开销大,而且短连接在批量更新时容易造成“惊群效应”——所有设备同时请求,服务器瞬间被打爆。
HTTP适合宽带、高算力的设备,比如智能网关、边缘服务器。我建议用HTTP/2,它支持多路复用,能减少连接数。
另外,HTTP的Range请求头天然支持断点续传。这个后面会细说。
4.5 更新服务器架构
协议选好了,服务器怎么搭?我画了一张架构图,你看一眼就明白:
架构分三层:
- 协议网关层:负责设备接入。MQTT Broker、CoAP Proxy、HTTP负载均衡器都在这一层。我建议网关层做流量整形,比如限制每台设备的最大下载速度,防止网络被占满。
- 更新调度层:核心逻辑在这里。它决定“谁先更新”、“什么时候更新”、“失败了怎么办”。我习惯用分批策略,先更新10%的设备,观察24小时没问题再全量推送。
- 存储层:固件包和状态数据分开存。固件包用对象存储(比如MinIO或S3),状态数据用关系型数据库或Redis。这样查询状态时不会影响固件下载。
4.6 断点续传:别让设备从头再来
物联网设备经常在弱网环境下工作。下载到一半断网了,如果从头开始,用户会疯掉。
断点续传的核心是记录已接收的字节偏移量。设备每次请求时带上偏移量,服务器从偏移量开始继续发送。
HTTP的Range请求头天然支持:
GET /firmware/v2.1.bin HTTP/1.1
Host: ota.example.com
Range: bytes=1048576-
服务器返回206 Partial Content,从第1MB开始发。
MQTT和CoAP没有原生断点续传。我一般自己实现:
- 设备每收到一块数据(比如64KB),就向服务器上报
offset。 - 服务器记录在状态数据库里。
- 重连后,设备从最后一个确认的offset开始请求。
4.7 差分更新:省流量、省时间
差分更新(Delta Update)只传输固件变化的部分。比如固件从2.0升到2.1,可能只改了10KB,差分包就只传10KB,而不是整个2MB的固件。
常用的差分算法有:
- bsdiff:基于二进制差分,压缩率高,但计算开销大。适合服务器端生成差分包。
- HDiffPatch:比bsdiff快,内存占用低。我在资源受限的网关上用过,效果不错。
- xdelta:基于VCDIFF标准,适合文本或结构化数据。
差分更新的流程:
- 服务器根据设备当前版本,生成差分包。
- 设备下载差分包。
- 设备用本地旧固件 + 差分包,合成新固件。
- 校验新固件的哈希值,确认无误后写入。
另外,差分更新不是万能的。如果固件版本跨度太大(比如从1.0直接升到3.0),差分包可能比全量包还大。我一般设定一个阈值:差分包超过全量包的80%时,直接下发全量包。
4.8 小结
协议选型没有银弹。MQTT适合批量推送,CoAP适合极低功耗设备,HTTP适合高算力网关。服务器架构要分层解耦,断点续传和差分更新是提升更新成功率的两个关键手段。