部署工程化:版本管理、热更新与异常处理
模型能跑起来只是第一步,生产环境稳定运行才是难点。版本管理、热更新、异常处理、监控告警、日志排查……这些工程化的东西决定了产品能不能长期稳定运行。这篇讲边缘AI部署的工程化实践。
大家好,我是黒漂技术佬。
做 demo 和做产品是两回事。demo 能跑就行,产品要 7×24 小时稳定运行,出了问题能快速定位、快速回滚、远程升级。
售货柜是投放出去的设备,不可能天天有人去现场维护。远程升级、异常自恢复、监控告警,这些都是必须的。
这篇讲边缘AI部署的工程化实践,都是实际踩坑踩出来的经验。
一、模型版本管理
为什么需要版本管理?
- 模型要迭代,新模型上线前要测试
- 新模型有问题要能快速回滚
- 不同批次的设备可能跑不同版本
- 出问题要知道当时跑的是哪个版本
版本号规范
建议语义化版本:主版本.次版本.修订号
v1.2.3 │ │ └─ 小优化、数据更新 │ └──── 新增功能、精度提升 └────── 架构变更、不兼容升级每次发布都有明确的版本号,变更记录写清楚。
模型文件命名
yolov8n_goods_v1.2.3_20260702.rknn │ │ │ └─ 构建日期 │ │ └─────────── 版本号 │ └───────────────── 模型用途 └──────────────────────── 基础模型一眼就能看出是什么模型、哪个版本、什么时候出的。
版本元数据
每个模型带一个配置文件,记录详细信息:
{"model_name":"goods_detection","version":"1.2.3","build_date":"2026-07-02","base_model":"yolov8n","input_size":[640,640],"quant_type":"INT8","classes":56,"mAP":0.962,"dataset_version":"v2.1","changelog":["新增 5 种商品类别","优化反光场景检测精度","校准集更新,量化精度提升"]}出问题的时候,看一眼配置就知道这个模型的基本信息。
模型仓库
所有历史版本模型统一存档,不要丢:
- 每个版本的模型文件
- 对应的配置文件
- 训练日志、测试报告
- 对应版本的数据集快照
回滚、对比、排查问题都需要。
二、模型热更新
设备投出去了,要升级模型总不能派人去现场插 U 盘吧?远程热更新是必须的。
更新流程
云端发布新版本 → 设备检测到更新 → 下载新模型 → 校验 → 切换加载 → 生效关键要点
1. 原子切换
不能加载到一半崩了,模型就废了。
做法:
- 新模型下载到临时文件
- 校验通过(MD5、版本号)
- 原子替换(rename,操作系统保证原子性)
- 推理服务重新加载
2. 版本校验
下载完校验完整性和正确性:
- MD5/SHA 校验,防止下载损坏
- 版本号检查,防止降级或错版本
- 模型格式校验,确保能正常加载
3. 自动回滚
新模型加载失败、或者运行一段时间异常率太高,自动切回旧版本。
加载新模型 → 成功 → 运行 → 监控异常率 → 异常高 → 自动回滚 → 失败 → 直接回滚4. 灰度发布
不要所有设备一起更,先更一小部分:
- 先更 5% 设备,观察 24 小时
- 没问题再更 20%
- 再没问题全量推送
新模型有问题也只影响一小部分设备。
增量更新
模型文件几 MB 到几十 MB,全量下载费流量。可以做差分更新:
- 只下载和旧版本的差异部分
- 本地合成新模型
嵌入式设备流量贵的场景值得做。
三、异常处理体系
生产环境一定会出问题,关键是出了问题能不能自己恢复、会不会影响全局。
分级异常处理
级别 1:瞬时错误(自动重试)
- 网络抖动
- 一帧推理超时
- 临时资源不足
处理:自动重试,记个 warn 日志,不用告警。
级别 2:单路异常(单路重启)
- 某一路摄像头断流
- 某一路推理连续失败
- 单路内存异常
处理:那一路自动重启,不影响其他路。记 error 日志。
级别 3:全局异常(服务重启)
- NPU 挂了
- 内存泄漏严重
- 核心模块崩溃
处理:整个推理服务重启,看门狗拉起。告警通知。
级别 4:系统级异常(设备重启)
- 系统级错误
- 驱动崩溃
- 硬件异常
处理:设备重启。严重告警。
常见异常与应对
| 异常 | 原因 | 处理 |
|---|---|---|
| RTSP 断流 | 网络波动、摄像头重启 | 自动重连,3秒重试 |
| 推理超时 | NPU 调度异常 | 跳过这帧,下一帧继续 |
| 模型加载失败 | 文件损坏、版本不对 | 回滚到上一个版本 |
| 内存持续增长 | 内存泄漏 | 监控阈值,达到就重启服务 |
| NPU 异常 | 驱动问题、硬件故障 | 复位 NPU,不行就重启 |
| 帧率持续过低 | 算力不够、资源竞争 | 自动降帧率、降分辨率 |
四、监控与告警
看不见的系统最可怕。一定要有监控。
需要监控的指标
性能指标
- 推理延迟(平均、P95、最大)
- 帧率(fps)
- 预处理/后处理耗时
- NPU 利用率
- CPU 使用率
- 内存占用
业务指标
- 每秒检测目标数
- 各类别检测数量
- 置信度分布
- 异常检测结果数量
健康指标
- 服务运行时长
- 重启次数
- 各摄像头连接状态
- 模型版本号
告警规则
- 推理延迟 P95 > 阈值 → 告警
- 帧率持续低于阈值 5 分钟 → 告警
- 内存占用 > 80% → 告警
- 摄像头断流超过 1 分钟 → 告警
- 服务重启 → 告警
- 异常检测率突增 → 告警
日志规范
日志分级
- DEBUG:调试信息,默认关闭
- INFO:正常运行信息
- WARN:异常但自动恢复了
- ERROR:出错了,需要关注
- FATAL:严重错误,服务挂了
关键日志点
- 服务启动/停止
- 模型加载/切换
- 摄像头连接/断开
- 推理异常
- 自动重连/重启
日志带上下文
[2026-07-02 14:30:21] [ERROR] [cam01] 推理超时,耗时 150ms,跳过该帧带上时间、级别、模块 ID,排查问题的时候一目了然。
五、配置管理
不同设备可能配置不一样,不能硬编码。
配置文件
# 摄像头配置cameras:-id:cam01rtsp_url:rtsp://admin:xxx@192.168.1.10/stream1resolution:1920x1080fps:25roi:[560,200,800,600]# 检测区域# 模型配置model:path:models/yolov8n_goods_v1.2.3.rknnconf_threshold:0.3iou_threshold:0.45input_size:640# 推理配置inference:npu_core:autotarget_fps:20skip_frame:false# 日志配置log:level:INFOfile:logs/inference.logmax_size:100MB配置热加载
改配置不用重启服务,发个信号 reload 一下:
- 阈值调整
- ROI 区域修改
- 帧率调整
这些运行时改的参数,支持热加载,方便现场调试。
六、启动脚本与守护进程
程序崩了要能自动拉起来。
systemd 守护
Linux 上用 systemd 管理服务:
[Unit] Description=AI Inference Service After=network.target [Service] Type=simple ExecStart=/opt/ai_service/bin/inference_server WorkingDirectory=/opt/ai_service Restart=always RestartSec=3 User=aiuser [Install] WantedBy=multi-user.target崩溃了 3 秒后自动重启。
看门狗
更底层的硬件看门狗,程序彻底挂了系统都能复位。
RK3588 有硬件看门狗,应用层定时喂狗,程序卡死不喂狗了,系统自动重启。
启动自检
服务启动时做一遍自检:
- 模型能不能加载
- 摄像头能不能连上
- NPU 能不能正常推理
- 内存够不够
自检失败直接报错退出,让守护进程重启,不要带病运行。
七、资源管理
内存控制
- 预分配内存池,上限可控
- 定期检查内存占用
- 超过阈值主动释放缓存、重启服务
RK3588 内存和系统共享,推理占太多会影响其他服务。
CPU 亲和性
前面讲过,推理线程绑大核,IO 线程绑小核,避免互相抢资源。
优先级设置
关键推理线程优先级高一点,保证实时性。
// 设置线程优先级structsched_paramparam;param.sched_priority=50;pthread_setschedparam(pthread_self(),SCHED_FIFO,¶m);温度与功耗
- 温度过高自动降频、降帧率
- 电池供电设备可以切换省电模式
- 防止过热死机
八、灰度与 A/B 测试
新模型上线,怎么确认效果真的好?
灰度发布
- 选一小部分设备跑新版本
- 跑一段时间(几天到一周)
- 对比新旧版本的业务指标
- 新版本确实好再全量
A/B 测试
同一台设备上两个模型并行跑(或者分时跑),对比结果:
- 精度差异
- 速度差异
- 误检漏检差异
确保新版本确实更好再全量推。
回滚预案
每次发布前都要想好:出问题怎么回滚?回滚到哪个版本?回滚多久生效?
别等出了问题才手忙脚乱找旧版本。
九、实际案例:售货柜的工程化方案
服务架构
AI 推理服务(systemd 守护) ├── 模型管理器(版本管理、热加载) ├── 多路推理流水线 ├── 配置管理器(热加载) ├── 监控指标采集 ├── 日志模块 └── 异常自恢复升级流程
- 云端发布新模型,灰度 5% 设备
- 设备后台下载,校验 MD5
- 凌晨低峰期自动切换
- 运行 24 小时,对比业务指标
- 没问题逐步扩大范围,有问题自动回滚
异常处理
- 摄像头断流:自动重连,3 秒一次,连不上 5 分钟后告警
- 推理连续失败 10 次:重启推理模块
- 内存超过 70%:触发告警,超过 85% 自动重启服务
- 服务崩溃:systemd 自动拉起,连续崩 3 次告警
监控
- 设备状态在线上报云端
- 帧率、延迟、内存、温度实时监控
- 异常自动告警到运维群
- 日志可以远程拉取排查
十、常见坑
坑 1:更新到一半断电,模型文件损坏
模型废了,服务起不来。
解决:下载到临时文件,校验通过再原子替换;保留上一个版本,损坏了自动回滚。
坑 2:内存泄漏,跑几天就崩
C++ 代码写不好容易泄漏,跑几天内存满了。
解决:内存池、定期检查、阈值告警、实在不行定时重启。
坑 3:日志打满磁盘
DEBUG 日志忘关了,几天打满磁盘。
解决:日志轮转、大小限制、分级输出。
坑 4:新版本兼容问题
新模型改了输出格式,老版本推理代码解析出错。
解决:版本号校验、向前兼容、格式变更走大版本号。
坑 5:异常自恢复变成无限重启
有问题就重启,越重启越频繁,陷入循环。
解决:加退避策略(重启间隔越来越长)、连续失败 N 次就告警停止。
十一、本篇小结
- 模型版本管理:语义化版本、元数据齐全、历史存档
- 热更新:原子切换、校验、自动回滚、灰度发布
- 异常分级处理:瞬时重试、单路重启、服务重启、设备重启
- 监控告警:性能指标 + 业务指标 + 健康指标
- 配置管理:配置文件 + 热加载,不要硬编码
- 守护进程:systemd + 看门狗,崩溃自动拉起
- 资源管理:内存控制、CPU 绑核、温度功耗
- 灰度发布:小范围验证,没问题再全量,有问题可回滚
下一篇是本系列最后一篇:售货柜实战——端到端优化落地全记录,把整个系列的知识串起来。
我是黒漂技术佬。