4. OTA交付系统架构设计
OTA交付系统不是“把固件包放到服务器上让设备下载”这么简单。对于 Jetson 设备,一次完整的 OTA 交付要同时解决五个问题:云端如何组织版本与差分包、网络链路如何保证弱网下的可靠传输、设备端如何安全地落盘与切换、更新代理如何编排整个流程、失败后如何回滚到已知可用状态。这五个问题分别对应架构中的五个关键域,任何一个域设计不当,都会导致“包发出去了但设备变砖”或“回滚不回去”的严重后果。
整体架构分层
推荐采用“云端控制面 + 设备端数据面”的分层架构。云端控制面负责版本元数据、差分包生成、灰度策略、设备分组和状态看板;设备端数据面负责下载、校验、写入、切换和回滚。两者之间通过一条轻量级控制通道(通常基于 MQTT 或 HTTPS 长轮询)交换“版本清单”和“状态上报”,而真正的固件数据走独立的下载通道(HTTPS 或 CDN),避免控制消息被大流量阻塞。
下图给出一个可直接落地的整体架构,包含云端、网络链路、设备端更新代理、A/B 分区与回滚机制五个部分,并标注了关键组件选型建议。
关键组件选型与理由
云端版本仓库建议使用对象存储(S3 兼容)保存全量包与差分包,元数据放 PostgreSQL。差分生成器优先选 bsdiff 或 zchunk:bsdiff 压缩率高但内存占用大,适合在云端离线生成;zchunk 支持分块校验和断点续传,更适合设备端按需拉取。对于 Jetson 的 L4T 根文件系统,差分包通常能压到全量包的 15%~30%,在 4G 网络下可显著缩短下载时间。
控制通道选 MQTT over TLS,原因是它天然支持长连接、低功耗和主题订阅,适合大量设备同时在线。设备订阅 ota/device/{sn}/cmd,云端下发版本清单;设备向 ota/device/{sn}/status 上报进度。数据通道走 HTTPS 或 CDN,支持 Range 请求实现断点续传。弱网策略包括:指数退避重试(初始 5s,最大 300s)、单连接限速、分片下载(建议 4MB 一片)。
设备端更新代理建议实现为 systemd 服务,开机自启,独立于业务应用。它负责:拉取清单、比对版本、下载差分包、校验签名、写入非活动分区、更新引导配置、触发重启、上报状态。代理本身要尽量小,避免依赖业务运行时,否则业务崩溃时更新代理也无法工作。
A/B 分区与回滚是 Jetson OTA 的核心。Jetson 的 U-Boot 支持 bootcount 和 altbootcmd,可以实现“启动失败自动回退”。典型配置:在 extlinux.conf 中设置 DEFAULT 指向新分区,同时设置 bootlimit=3;每次启动 U-Boot 递增 bootcount,若成功进入系统则由用户态清零;若连续 3 次未清零,U-Boot 自动切回旧分区。健康检查项建议至少包含:网络可达、推理服务响应、关键磁盘挂载、GPU 驱动加载。
一次典型 OTA 交付的数据流
假设设备当前运行 L4T 35.4.1,云端发布 35.5.0。流程如下:云端生成 35.4.1→35.5.0 的差分包,写入对象存储,并在设备注册表中标记目标分组。设备代理通过 MQTT 收到清单,比对本地版本后发起 HTTPS 下载,分片写入 B 分区。下载完成后校验 SHA256 与 Ed25519 签名,通过则更新 extlinux.conf 的 DEFAULT 为 B,设置 bootlimit=3,重启。重启后若健康检查通过,代理执行 commit,清零 bootcount,上报成功;若失败,U-Boot 在第三次启动时自动回退到 A,代理上报回滚事件。
架构设计中的常见陷阱
- 把控制通道和数据通道混在一起:大包下载会阻塞 MQTT 心跳,导致设备被误判离线。必须分离。
- 回滚依赖业务应用:如果健康检查由业务应用执行,业务崩溃时无法触发回滚。健康检查应放在更新代理或独立看门狗中。
- 差分包不做签名:只校验 SHA256 不够,攻击者可替换包并重算哈希。必须使用设备端预置公钥验证 Ed25519 签名。
- 忽略 bootcount 清零时机:清零太早(如刚进系统就清零)会导致业务未就绪就确认成功;清零太晚则可能误触发回滚。建议在健康检查全部通过后清零。
整体来看,OTA 交付系统的架构设计核心是“控制与数据分离、更新与业务解耦、回滚不依赖业务”。把这三点落实到组件选型和状态迁移上,才能让 Jetson 设备在弱网、断电、业务异常等真实条件下依然能安全完成版本切换。