一、方案概述
本方案针对第三方采购安卓工控机的 OTA 升级场景,基于 SpringBoot 服务端 + MQTT 通讯 + 工控机本地守护服务 实现,覆盖 "升级触发→包下载→安装→启动检测→失败回滚→状态监控" 全流程,核心目标是:安全可靠、无人干预、业务无感知、故障可恢复,适配工控机无 root / 有限权限、工业环境网络不稳定、业务连续性要求高等特性。
二、核心架构设计
(一)整体架构图
plaintext
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ SpringBoot 服务端 │ │ MQTT 服务器 │ │ 安卓工控机客户端 │
├─────────────────┤ ├─────────────────┤ ├─────────────────┤
│ 1. 设备管理模块 │◄────►│ 1. 消息路由 │◄────►│ 1. MQTT 通讯模块 │
│ 2. 升级包管理模块 │ │ 2. 会话持久化 │ │ 2. OTA 核心服务 │
│ 3. 指令下发模块 │ │ 3. 离线消息缓存 │ │ 3. 启动检测守护进程 │
│ 4. 状态监控模块 │ │ 4. 权限控制 │ │ 4. 回滚执行模块 │
│ 5. 日志告警模块 │ │ │ │ 5. 本地存储管理 │
└─────────────────┘ └─────────────────┘ └─────────────────┘
▲ ▲ ▲
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 文件服务器 │ │ 数据库 │ │ 本地存储 │
│ (MinIO/NFS) │ │ (MySQL/PostgreSQL)│ │ - 升级包缓存 │
│ - 存储升级包 │ │ - 设备信息 │ │ - 原版本备份 │
│ - 提供下载URL │ │ - 升级日志 │ │ - 状态文件 │
│ │ │ - 包元信息 │ │ - 日志文件 │
└─────────────────┘ └─────────────────┘ └─────────────────┘
(二)核心组件职责
| 组件 | 核心职责 |
|---|---|
| SpringBoot 服务端 | 设备注册 / 认证、升级包上传 / 管理、升级指令下发、状态接收、日志存储、告警触发 |
| MQTT 服务器 | 负责服务端与工控机的消息传输,保障离线消息缓存、消息可靠送达(QoS=1) |
| 工控机客户端 | 接收升级指令、下载升级包、备份原版本、执行安装、启动检测、失败回滚、状态上报 |
| 文件服务器 | 存储升级包(避免服务端存储压力),提供 HTTP 下载链接 |
| 数据库 | 持久化设备信息、升级包元信息、升级 / 回滚日志,支持后续追溯与统计 |
三、前置条件与环境准备
(一)服务端环境
- 基础环境:JDK 11+、Maven 3.6+、MySQL 8.0+;
- MQTT 服务器:EMQ X/ActiveMQ(支持 MQTT 3.1.1,配置持久化会话、QoS=1);
- 文件服务器:MinIO(轻量、支持 HTTP 下载、Range 断点续传);
- 网络:确保服务端、MQTT 服务器、文件服务器可被工控机访问(工业内网 / 公网穿透)。
(二)工控机客户端环境
- 系统要求:Android 7.0+(兼容低版本 API);
- 权限要求:至少具备
REQUEST_INSTALL_PACKAGES(安装 APK)、WRITE_EXTERNAL_STORAGE(存储升级包 / 备份)、INTERNET(MQTT/HTTP 通讯)权限;若需静默安装 / 回滚,需厂商提供系统签名(无需 root); - 存储要求:预留≥2 倍于升级包大小的空闲空间(推荐本地存储,避免 SD 卡掉卡);
- 预装组件:MQTT 客户端、OTA 核心服务、启动检测守护进程(按前文方案实现)。
四、详细流程设计(全链路 Step-by-Step)
阶段 1:系统初始化与设备注册
1. 设备注册(首次联网触发)
-
工控机启动后,OTA 核心服务自动初始化,通过 MQTT 连接服务器(客户端 ID = 设备 SN 码,username=SN 码,password=MD5 (SN + 盐值));
-
工控机上报设备基础信息(主题:
ota/device/{deviceSn}/register),消息体:json
{ "deviceSn": "SN_202501010001", "deviceModel": "IPC-Android-3288", "currentVersion": "V1.0.2", "systemVersion": "Android 9.0", "ipAddress": "192.168.1.100", "hardwareInfo": "CPU:ARM64,RAM:4G,ROM:64G", "timestamp": 1734567890000, "sign": "md5(deviceSn+timestamp+secret)" } -
服务端校验设备合法性(SN 码是否已录入系统),校验通过后存储设备信息,返回注册成功响应(主题:
ota/server/device/{deviceSn}/resp)。
2. 心跳上报(持续在线)
-
工控机每 60 秒上报一次心跳(主题:
ota/device/{deviceSn}/status),消息体简化为:json
{ "deviceSn": "SN_202501010001", "status": "ONLINE", "currentVersion": "V1.0.2", "timestamp": 1734567950000, "sign": "md5(deviceSn+status+timestamp+secret)" } -
服务端通过心跳更新设备在线状态,超过 180 秒未收到心跳则标记为 "OFFLINE"。
阶段 2:升级包管理(服务端操作)
1. 升级包上传与审核
- 管理员通过服务端后台上传升级包(APK 文件),填写元信息:设备型号(适配范围)、目标版本、最低支持版本、MD5 校验码、数字签名、升级描述、维护窗口;
- 服务端将升级包上传至 MinIO 文件服务器,生成唯一下载 URL,数据库存储包元信息(状态为 "草稿");
- 管理员审核通过后,升级包状态更新为 "已发布",支持按设备型号、当前版本筛选下发范围。
2. 升级包元信息示例(数据库表结构)
| 字段名 | 类型 | 说明 | 示例 |
|---|---|---|---|
| id | BigInt | 主键 ID | 1001 |
| deviceModel | String | 适配设备型号(多个用逗号分隔) | "IPC-Android-3288,IPC-Android-4418" |
| version | String | 升级包版本(语义化) | "V2.0.0" |
| apkUrl | String | MinIO 下载 URL | "http://minio:9000/ota/V2.0.0.apk" |
| apkSize | Long | 包大小(字节) | 2147483648(2GB) |
| md5 | String | MD5 校验码 | "e10adc3949ba59abbe56e057f20f883e" |
| signature | String | RSA 数字签名(防篡改) | "MIIBIjANBgkqhkiG9w0BAQEFAAO..." |
| minSupportVersion | String | 最低支持版本(低于则不可升级) | "V1.0.0" |
| maintenanceWindow | JSON | 维护窗口(开始 / 结束时间戳) | {"start":1734576000000,"end":1734583200000} |
| description | String | 升级描述 | "修复稳定性问题,优化网络传输" |
| status | Integer | 状态(0 = 草稿,1 = 已发布,2 = 已下架) | 1 |
| releaseTime | Long | 发布时间戳 | 1734500000000 |
阶段 3:升级触发与执行(服务端 + 工控机协同)
1. 升级触发方式
- 自动触发:服务端按设备型号 + 当前版本筛选目标设备,定时(如凌晨 2 点)下发升级指令;
- 手动触发:管理员在服务端后台选择单个 / 批量设备,手动下发升级指令;
- 设备主动查询:工控机每 24 小时主动向服务端请求版本信息(主题:
ota/device/{deviceSn}/query),服务端返回是否有可用升级包。
2. 升级指令下发(服务端→工控机)
-
主题:
ota/device/{deviceSn}/cmd -
消息体(QoS=1,确保必达): json
{ "cmdType": "UPGRADE", "upgradeInfo": { "targetVersion": "V2.0.0", "apkUrl": "http://minio:9000/ota/V2.0.0.apk", "apkSize": 2147483648, "md5": "e10adc3949ba59abbe56e057f20f883e", "signature": "MIIBIjANBgkqhkiG9w0BAQEFAAO...", "forceUpgrade": false, "maintenanceWindow": {"start":1734576000000,"end":1734583200000}, "description": "修复稳定性问题,优化网络传输" }, "timestamp": 1734568000000, "nonce": "random123456", "sign": "md5(cmdType+targetVersion+timestamp+nonce+secret)" }
3. 工控机接收指令与预处理
- 工控机校验指令签名(防篡改),若当前处于维护窗口外且非强制升级,上报
UPGRADE_WAITING状态(等待维护窗口); - 若在维护窗口内,执行原版本备份:
- 备份内容:当前 APK(路径:
/data/local/ota/backup/{deviceSn}_v{currentVersion}_xxx.apk)、核心配置文件(/data/local/ota/backup/config/); - 记录备份元信息(版本号、MD5、路径)至本地状态文件(
/data/local/ota/state/upgrade_state.json); - 备份失败则上报
BACKUP_FAILED(错误码 4),终止升级。
- 备份内容:当前 APK(路径:
- 备份成功后,上报
UPGRADE_READY状态,准备下载升级包。
4. 升级包下载(支持断点续传)
-
工控机通过 HTTP 下载升级包(存储路径:
/data/local/ota/download/new.apk),利用 Range 请求实现断点续传:- 首次下载:请求
Range: bytes=0-,开始下载; - 网络中断后恢复:读取已下载字节数,请求
Range: bytes=xxx-,从断点继续;
- 首次下载:请求
-
实时上报下载进度(主题:
ota/device/{deviceSn}/progress):json
{ "deviceSn": "SN_202501010001", "targetVersion": "V2.0.0", "progressType": "DOWNLOAD", "progress": 68, "downloadedSize": 1460288901, "totalSize": 2147483648, "timestamp": 1734568500000, "sign": "md5(deviceSn+progressType+progress+timestamp+secret)" } -
下载失败处理:重试 3 次,仍失败则上报
DOWNLOAD_FAILED(错误码 1),终止升级。
5. 升级包校验
- 下载完成后,工控机计算本地 APK 的 MD5 值,与指令中的
md5比对; - 若配置了数字签名,通过公钥验证
signature(防包被篡改); - 校验失败则上报
VERIFY_FAILED(错误码 2),删除下载的 APK,终止升级。
6. 静默安装升级包
-
工控机执行安装命令(需系统签名,无需 root): bash
运行
pm install -r -d /data/local/ota/download/new.apk # -r=覆盖安装,-d=允许降级(后续回滚用) -
安装过程中每 10 秒上报进度(
progressType=INSTALL,进度 70%-90%); -
安装失败处理:重试 2 次,仍失败则上报
INSTALL_FAILED(错误码 3),触发回滚。
7. 安装完成重启
- 安装成功后,工控机自动重启(
reboot命令),重启前更新本地状态:currentState="REBOOT_AFTER_INSTALL"; - 重启后,启动检测守护进程自动激活(阶段 4 核心流程)。
阶段 4:启动检测与失败回滚
1. 启动检测(守护进程执行)
按前文定义的 5 个维度检测新 APK 启动状态,任一维度触发失败阈值则判定 "启动失败":
- 30 秒内进程未存在→失败;
- 60 秒内进程闪退≥2 次→失败;
- 40 秒内业务端口未监听→失败;
- 20 秒内健康检查失败→失败;
- 90 秒内未上报
APP_START_SUCCESS心跳→失败。
2. 启动成功处理
- 检测通过后,工控机上报
APP_START_SUCCESS状态(主题:ota/device/{deviceSn}/status),更新本地状态为UPGRADE_SUCCESS; - 服务端接收状态后,更新设备当前版本为目标版本,记录升级成功日志,清理设备备份(保留最近 3 个版本)。
3. 启动失败回滚(自动触发)
- 检测守护进程生成启动失败报告,捕获启动日志,调用回滚脚本;
- 回滚步骤(详细见前文):
- 预处理:停止新 APK 进程、释放端口、清理残留;
- 备份校验:检查原版本备份文件存在性 + MD5 一致性;
- 安装原版本:执行
pm install -r 备份路径; - 恢复配置:将备份的配置文件复制回原路径;
- 重启验证:重启工控机,检测原版本启动状态;
- 状态上报:回滚成功上报
ROLLBACKED,失败上报ROLLBACK_FAILED(错误码 7-11)。
- 服务端接收回滚状态后,触发告警(短信 / 邮件),锁定该升级包(禁止自动下发),等待管理员排查问题。
阶段 5:监控、日志与告警(服务端核心能力)
1. 全流程日志记录
- 服务端日志:记录指令下发时间、设备状态变更、升级 / 回滚结果、错误原因,存储周期≥90 天;
- 工控机日志:记录下载进度、安装日志、启动检测日志、回滚日志,支持通过 MQTT 上传至服务端(主题:
ota/device/{deviceSn}/log/upload)。
2. 实时监控面板
服务端后台提供可视化监控:
- 设备状态统计:在线 / 离线设备数、升级中 / 待升级 / 已升级设备数;
- 升级进度统计:各设备下载进度、安装进度、回滚进度;
- 成功率统计:升级成功率、回滚成功率、失败原因分布(如下载失败占比、启动失败占比)。
3. 告警机制
触发以下场景时,服务端发送告警(支持短信、邮件、后台弹窗):
- 升级失败:设备升级过程中上报
FAILED状态; - 回滚失败:上报
ROLLBACK_FAILED状态(尤其是原版本也启动失败); - 批量异常:同一升级包下发后,启动失败率≥5%;
- 设备离线:关键设备离线超过 30 分钟。
五、关键技术保障
(一)通讯可靠性
- MQTT 配置:
cleanSession=false(保留会话)、QoS=1(升级 / 回滚指令)、keepAliveInterval=60s(心跳); - 离线消息:MQTT 服务器缓存离线期间的指令,设备重连后自动接收;
- 消息重试:工控机上报状态失败时,缓存消息,重连后自动重试(最多 3 次);
- 遗嘱消息:工控机设置遗嘱(
willTopic=ota/device/{deviceSn}/status,willMessage={"status":"OFFLINE"}),服务端快速感知设备离线。
(二)数据安全性
- 身份认证:设备连接 MQTT 时通过
username/password(SN + 密钥)校验,服务端仅允许合法设备连接; - 消息防篡改:所有指令 / 状态上报均携带 MD5 签名(含密钥),接收方校验后再处理;
- 升级包防篡改:通过 MD5 校验 + RSA 数字签名双重保障,避免包被替换 / 篡改;
- 权限控制:工控机仅授予 OTA 服务必要权限,避免过度授权;服务端按角色分配权限(如管理员可下发指令,操作员仅可查看监控)。
(三)工业环境适配
- 断点续传:下载升级包支持 HTTP Range 请求,应对工业网络中断频繁问题;
- 维护窗口:升级 / 回滚仅在维护窗口内执行(可配置),避免业务高峰期中断;
- 低资源占用:工控机 OTA 服务 + 守护进程内存占用≤20MB,CPU 占用≤5%,不影响业务运行;
- 断电保护:工控机本地状态文件实时更新,断电后重启可恢复之前的升级 / 回滚进度。
(四)兼容性适配
- 系统版本兼容:支持 Android 7.0+,适配
FileProvider(Android 7.0+ 文件访问)、动态权限申请(Android 6.0+); - 设备型号适配:升级包按设备型号筛选下发,避免跨型号升级导致不兼容;
- 权限兼容:无 root 时,依赖系统签名实现静默安装;若无法获取系统签名,可协商厂商开放
INSTALL_PACKAGES权限。
六、部署与测试方案
(一)部署步骤
- 服务端部署:
- 部署 MySQL 数据库(初始化设备表、升级包表、日志表);
- 部署 MinIO 文件服务器(创建 OTA 存储桶,配置访问权限);
- 部署 MQTT 服务器(配置持久化、心跳、权限);
- 部署 SpringBoot 服务(配置 MQTT 连接、数据库连接、MinIO 连接)。
- 工控机部署:
- 预装 OTA 核心服务(APK 形式,开机自启);
- 预装启动检测守护进程(Native 进程 / 系统服务,按前文方案实现);
- 配置 MQTT 连接参数(服务器地址、端口、设备 SN、密钥);
- 初始化本地存储目录(
/data/local/ota/download/、/data/local/ota/backup/、/data/local/ota/logs/)。
(二)测试方案
- 功能测试:
- 正常升级流程测试:下发合法升级包,验证 "下载→安装→启动成功→状态上报" 全流程;
- 启动失败回滚测试:按前文方案模拟新 APK 启动失败,验证 "检测→回滚→原版本恢复";
- 异常场景测试:网络中断、断电、升级包损坏、权限缺失等场景下的流程完整性。
- 性能测试:
- 并发测试:同时向 100 台设备下发升级指令,验证服务端、MQTT 服务器抗压能力;
- 资源占用测试:监控工控机升级过程中 CPU、内存、网络占用,确保不影响业务。
- 兼容性测试:
- 在目标工控机型号 + 不同安卓版本(如 Android 7.0、9.0、11.0)上验证升级流程。
七、运维与迭代
- 日常运维:
- 定期清理过期日志(服务端 90 天,工控机 30 天);
- 定期检查升级包存储(MinIO 磁盘空间);
- 监控 MQTT 服务器、服务端运行状态(如 CPU、内存、连接数)。
- 迭代优化:
- 根据失败原因优化流程(如增加下载重试次数、调整启动检测阈值);
- 新增功能(如支持升级包差分更新、远程日志调试、批量回滚);
- 适配新的工控机型号 / 安卓版本。
八、总结
本方案覆盖 OTA 升级全流程,核心优势在于:
- 适配第三方工控机:无需 root,依赖系统签名实现静默安装 / 回滚,非侵入式部署;
- 故障自动恢复:启动失败后自动回滚,确保业务不中断;
- 工业环境适配:断点续传、维护窗口、低资源占用,应对网络不稳定、业务连续性要求高的场景;
- 可监控可追溯:全流程日志 + 实时监控 + 告警,便于运维排查问题。
方案可直接落地,若工控机有特殊限制(如无法获取系统签名、文件目录只读),可调整 "安装方式""存储路径" 等细节,确保适配实际场景。