最佳实践2026-11-0212 分钟

物联网设备 OTA 升级:断点续传、灰度发布、失败回滚怎么设计

OTA 不是把固件推到设备就完事。一次失败的全量推送能让几千台设备同时变砖,断点续传、灰度、回滚三件事必须在第一次升级前就设计好。

哈咪
哈咪物联
哈咪物联技术团队
OTA固件升级灰度发布断点续传回滚

OTA 是所有物联网项目里最容易低估的功能。产品规划阶段大家都觉得「不就是把固件推下去让设备自己升吗」,真正上线后才发现,这是最容易造成批量事故的环节。

我见过最惨的一次:一个新版本固件全量推给了三千多台设备,其中一批设备的 Flash 空间比预期小 200KB,升级写到一半空间不足,设备卡在 bootloader 里起不来。现场没人,只能派人一台台去刷。那次之后,那家公司把所有 OTA 都改成了灰度。

这篇文章讲 OTA 必须做对的五件事:传输、分区、灰度、回滚、限速。按这个顺序设计,出事的概率会低很多。

一、传输:断点续传和分片校验是底线

设备端的网络环境通常比你想的差。4G 信号弱、WiFi 被挤占、NB-IoT 单次传输有大小限制,一个 2MB 的固件包传到 80% 断掉是常态。如果没有断点续传,下次只能从头再来,弱网环境下可能永远传不完。

实现要点:

  • 固件按固定大小分片,比如 4KB 或 16KB 一片
  • 设备上报已收到的分片位图,服务端返回缺失的分片
  • 每片带 CRC32 或 MD5,收到后立即校验,错了只重传这一片
  • 整包传完后做一次全量 SHA256 校验,通过才允许进入升级流程

位图可以用一个字节数组表示,1MB 的固件按 4KB 分片是 256 片,32 字节就能表示完整进度。这个位图存在设备的非易失存储里,断电重启后能继续。

不要用 HTTP Range 就以为做了断点续传。Range 只能从断点续传,如果中间某一片损坏,它发现不了。必须自己维护分片状态。

还有一个细节:分片大小要匹配设备的内存。MCU 只有 64KB RAM,你一次让它接收 64KB 的分片,加上协议栈开销就爆了。4KB 是个比较安全的默认值。

二、分区:A/B 双分区是唯一可靠方案

单分区升级的流程是:擦除应用区 → 写入新固件 → 重启。这个流程有个致命问题:擦除之后、写完之前断电,设备就变砖了。没有 bootloader 兜底,只能返厂。

A/B 双分区的做法:Flash 分成两个等大的应用区 A 和 B,再加一个小的 bootloader 区。

  • 设备运行在 A 区时,新固件写到 B 区,A 区不受影响
  • 写完校验通过,在 bootloader 里标记「下次从 B 启动」
  • 重启进 B 区,如果能正常启动并连上服务器,标记 B 为有效,A 变成可覆盖区
  • 如果 B 区启动失败(看门狗超时或主动上报失败),bootloader 自动回退到 A

代价是 Flash 要双倍。128KB 的 MCU 可能装不下,那就得选 256KB 的型号,或者用外部 SPI Flash 存固件包。

小 Flash 设备的折中方案:如果实在做不了双分区,至少要做到「先下载完整包到外部存储,校验通过后再擦除写入」。这样把「下载失败」和「写入失败」两个风险隔开,只剩写入阶段的风险。再配合掉电检测,写入中断后从 bootloader 重新进入写入流程。

bootloader 必须独立且不可升级。如果把 bootloader 也做成可升级的,一次升级失败就彻底救不回来了。bootloader 区的写保护要打开。

三、灰度:1% → 10% → 50% → 100%

全量推送是赌博。正确的做法是分批,每一批观察足够长的时间再放大。

阶段比例观察时长放行条件
内测3-10 台(自有设备)24 小时全部升级成功且功能正常
灰度一1%24-48 小时成功率 ≥98%,无异常上报
灰度二10%24 小时成功率 ≥98%,崩溃率不高于旧版本
灰度三50%12-24 小时同上
全量100%——

灰度分组不要随机。随机分组会把不同批次、不同硬件版本、不同地域的设备混在一起,出问题时看不出规律。按维度分组更有价值:

  • 先选硬件版本最新的(兼容性最好,出问题影响面小)
  • 再选网络条件好的(排除网络因素干扰)
  • 再按地域分批(某个区域出问题能快速定位)

更实用的做法:先升内部测试设备,再升「配合度高」的客户设备,最后升全部。第一批出问题,你能打电话让人配合抓日志;等到大面积出问题,就来不及了。

关键指标:升级成功率、升级后 24 小时内的在线率、升级后 24 小时内的重启次数、业务数据上报是否正常。只看「升级成功」不够,有些固件升上去了但功能坏了,要业务指标才能发现。

四、回滚:什么条件下自动回滚

回滚分两种:主动回滚和被动回滚。

被动回滚是设备自己做的,在 bootloader 层实现:新固件启动后,如果在规定时间内没有完成「标记有效」的动作,bootloader 就认为启动失败,退回旧分区。这个动作通常是设备连上服务器并收到确认。

超时时间要留够:设备冷启动、连 WiFi、做 TLS 握手、上报第一条数据,整个过程可能需要 30-60 秒。设成 10 秒会导致正常启动的设备也被误判。

主动回滚是服务端发起的:发现某个版本有问题,下发指令让已升级的设备退回旧版本。这要求旧固件还留在设备上——如果已经被新固件覆盖,就回不去了。

所以 A/B 分区方案里,新固件运行稳定后,不要立即擦除旧分区。至少保留 7 天,或者保留到下一版本开始推送前。多占一点 Flash,换的是出问题时的退路。

触发主动回滚的条件要提前定义好,不能等出事了再临时判断:

  • 新版本设备在线率比旧版本低 5 个百分点以上,持续 2 小时
  • 新版本设备重启次数超过阈值(比如 24 小时内平均每台 3 次)
  • 新版本关键业务数据上报成功率下降超过 3%
  • 出现已知的致命缺陷(比如某个型号的模组不兼容)

五、限速:别让升级把带宽打满

这是最容易被忽略的一条。几千台设备同时开始下载固件,会瞬间打满服务器带宽,不仅 OTA 本身传不动,正常业务数据也上不来。

服务端限速:

  • 控制同时下载的设备数,比如并发上限 200 台
  • 单设备限速,比如每台 100KB/s
  • 按时间段限速,业务高峰期(白天)降低推送速率,夜间加速

设备端限速:

  • 设备检测到电池电量低于 30% 时暂不升级(除非是市电供电设备)
  • 4G 设备检测信号强度低于阈值时推迟,避免弱网重传浪费流量
  • NB-IoT 设备特别要注意:单次传输有大小限制,而且流量按次计费,一个大固件可能产生几十块钱流量费

流量成本要算清楚。2MB 固件 × 5000 台 = 10GB。如果设备用的是按流量计费的物联网卡,这笔钱可能是几千到上万。有些项目会在升级前给用户发通知,说明会产生流量,避免纠纷。

六、状态追踪:设备不回报怎么办

OTA 最难处理的状态是「不知道设备现在什么情况」。指令发出去了,设备没响应;下载开始了,进度停在 40% 不动了;重启了,但没上报结果。

状态机要设计完整:

状态含义超时处理
pending任务已创建,未下发—
sent已下发,等待设备确认24 小时无响应 → 标记失败
downloading设备正在下载进度 2 小时无变化 → 重试
verifying校验中30 分钟无变化 → 失败
installing正在写入10 分钟无变化 → 失败
rebooting重启中5 分钟无变化 → 检查是否变砖
success升级成功,设备已上报新版本号—
failed失败,需人工介入—

「success」的判定必须是设备主动上报新版本号,不能靠「重启后连上了就算成功」。因为回滚后设备也会连上,但版本号是旧的。

设备侧要做的:每个状态变化都上报一次,并且把当前状态存在非易失存储里。设备重启后能接着上报,不会因为重启丢状态。

对于失联设备,要有兜底机制:设备下次上线时主动查询有没有待执行的升级任务。这样离线期间错过的推送不会永久丢失。

七、低功耗设备的特殊处理

电池供电的设备(水表、气表、地磁、土壤传感器)OTA 要单独设计,因为它们大部分时间在休眠,只有定时唤醒上报数据的那几十秒是醒着的。

策略:

  • 把升级任务挂在唤醒周期里,每次唤醒只下载几个分片,下载完再睡
  • 一个 500KB 的固件按每天唤醒 4 次、每次传 8KB 算,需要 16 天
  • 升级期间不要执行其他业务,避免电量消耗叠加
  • 电量低于 50% 时暂停升级,等换电池或充电后继续

这类设备的 OTA 周期通常按月算,不适合做紧急修复。所以低功耗设备的关键缺陷修复要留后路:要么设计时预留远程配置能力(改参数不用改固件),要么接受「必须现场处理」的现实。

还有一个坑:有些低功耗设备用深度休眠,升级过程中如果看门狗没喂好会被复位。复位后如果没做断点续传,前面下的分片全丢。所以断点续传对这类设备是刚需,不是可选项。

上线前的检查表

  • 固件包分片了吗?分片大小匹配设备内存吗?
  • 每片有校验吗?整包有校验吗?
  • 断点续传的位图存在哪?断电会丢吗?
  • 是 A/B 双分区吗?bootloader 有写保护吗?
  • 新固件启动后多久内必须标记有效?超时时间够吗?
  • 旧分区保留多久?回滚还能回去吗?
  • 灰度分组按什么维度?第一批选谁?
  • 每一阶段的放行条件写死了吗?谁来判?
  • 主动回滚的触发条件定义了吗?谁有权触发?
  • 并发数和单设备速率限制了吗?
  • 流量成本算过吗?谁承担?
  • 状态机完整吗?每个状态的超时处理有吗?
  • 失联设备下次上线会补推吗?
  • 低功耗设备的唤醒周期内能传完吗?

OTA 的核心不是技术难度,是对失败的设计。假设每一次升级都会失败,然后设计好失败之后怎么办——这样的 OTA 才能放心用。

开始您的物联网之旅

注册哈咪IoT平台,免费体验设备接入、数据可视化和规则引擎等核心功能