业务代码往往不是大头。服务要烧进板子,断网还能干自己那点活,崩溃后日志说得清原因,升级到一半拔电也不能变砖。漏掉的通常就是这几件里的某一件,然后变成凌晨的上门。
云上那套习惯直接搬下来,内存和闪存经常先不够用。
01这句话到底在说什么
边缘设备,是算力和数据离现场更近的那一端。摄像头、网关、工控机、机器人、车机、收银机、家用盒子、塞在机柜里的小主机,都算。它们不一定小。放在现场,网不一定一直在,人摸得到,而且常常要维护很多年。
服务,是这块设备上长期跑着、对内或对外提供能力的那个进程,或故意拆开的一小簇进程。不是一次性脚本,也不是只在调试时打开的网页。它要开机自起,崩溃能回来,配置能换,版本能升,日志能解释它刚才为什么死了。
这篇的中心是:一块会离开你视线的设备,上面有一个你得负责的服务。纯传感器固件、纯云端 API、只在笔记本上跑的工具,会作为邻居出现,不占中心。邻居从三个口伸进来:朝下连摄像头、传感器、开关,朝上连云和人,以及编这个服务的构建机。前两个口在业界习惯叫南向和北向。那不是房间里的东南西北,只是画图时的上下。
02服务为什么要长在设备上
留下的理由
时延等不了往返:控制、快门、对讲、刹车。原始视频、点云、高频采样传上去比本地做完结论贵。原始画面按隐私不该离开现场。电梯井、船、车间、地下室里,网络是客人。
不该留下的理由
需要全局视图的调度、模型训练、跨设备账本、改得很勤却没有可靠下发通道的策略,以及任何「这块板子丢了业务就不可恢复」的唯一副本。这些放在设备上,是把总部的职责塞进前哨。
还有一条软理由容易被说成硬理由:数据已经在本地成型,搬去云上再算是倒手。这只在你真的量过带宽、延迟和故障成本之后才成立。没量过,它只是一句偏好。
03先把约束写成数字
动手之前把约束写成数字。形容词留不住设计。
- 算力:哪颗核,有没有 NPU 或 GPU,能持续跑还是只能突发。
- 内存:常驻预算,不是某次峰值看起来还行。没有交换分区时,超了就是杀进程。
- 盘:容量、介质、每天允许写多少。eMMC、NAND、SD、SSD 不是同一种消耗品。
- 电:常供电、电池还是 PoE;掉电是瞬间发生的,不是计划中的关机。
- 热:封闭外壳里连续推理十分钟,频率会掉到多少。
- 网:上行有多窄,有没有入站,断网按秒计还是按天计。
- 时间:有没有靠谱的 RTC,纽扣电池三年后还在不在。
- 手:现场的人会不会拔卡、短接调试口、用 U 盘「帮忙」。
- 寿命与成本:维护五年还是十五年;BOM 每多一块钱,乘以出货量。
这几行如果写的是「还行」或者「以后再说」,后面的方案就是在猜。猜错的部分,最后会变成现场工单。
04硬件:进程脚下的那块板
服务不直接认识「摄像头」。它认识驱动、设备节点和总线。要过一遍的面:
- 计算:ARM、x86、RISC-V;大核小核;NPU 是否只能跑特定算子,不支持的算子会不会悄悄退回 CPU。
- 启动介质:从哪启动,有没有 A/B 槽,写保护怎么做。
- 保存什么:RAM、RTC、EEPROM、安全元件或 TPM。校准数据和身份不该跟系统镜像死在一起。
- 总线和口:I2C、SPI、UART、CAN、USB、PCIe、MIPI、GPIO、以太网、无线。每一种都带自己的失败:接触不良、地址冲突、枚举顺序变化、热插拔。
- 看门狗:硬件看门狗由谁喂。业务线程喂自己,死锁时灯还在闪,等于没有。
- 执行器:失去心跳之后保持、归零,还是切断。三选一,写进行为,不要留在口头。
- 修订:同一产品名下,下一批板子换了网卡或摄像头座。把节点名和 GPIO 号焊死在业务里,量产周会停线。
硬件抽象要薄,也要显式:哪些能力是这一代都有的,哪些只在某个修订上有。探测失败就降级并说明原因,不要启动失败,也不要假装那路传感器还在。
05系统:谁来养活这个进程
常见底座是裁过的 Linux(Yocto、Buildroot,或 Debian、Ubuntu 的设备变体)、Android、RTOS(FreeRTOS、Zephyr 一类),偶尔是 Windows IoT。选底座就是在选:有没有包管理,有没有用户态隔离,实时能到哪一档,十年后还有没有人能把这套系统再编出来。
容器不是默认答案。内存和盘都紧的时候,一整套容器运行时是奢侈。设备够大、团队已经会、又需要和云上同一交付物时,再用。不够大时,一个边界清楚的二进制加上 systemd(或同等的初始化系统),往往更诚实。
根文件系统尽量只读,可变数据单独分区。临时文件放内存盘。初始化系统负责依赖顺序、重启策略、资源上限和日志去向。服务自己再写一套守护,通常是第二套会出 bug 的 init。
06一个进程,还是一群进程
云上的微服务习惯搬到设备上,经常先把内存吃掉:每个进程一份运行时、一份日志、一份健康检查,业务还没跑。默认从一个进程里的模块开始。拆开只在你能指着说的时候:
- 故障域必须隔开:推理崩了不能带走控制回路。
- 权限必须隔开:碰视频的代码不该拿着云端私钥。
- 更新节奏不同:协议适配每周变,核心一年才变。
- 实时性不同:控制用实时线程或单独进程,业务用更从容的运行时。
拆开之后马上要回答:谁先起,谁等谁,谁死了算整机不健康,共享状态放哪,端口和总线谁独占。没有这些答案,拆分只是文件夹美学。
语言跟着约束走。靠近硬件和实时的部分,C、C++ 或 Rust 更常见。服务本体用 Go 或 Rust,启动和依赖都好收。Python 适合胶水、产测和尚在变形的逻辑;内存紧张的常驻核心要先量过它的常驻和启动,再决定它能不能留下。垃圾回收的停顿放进时延预算里看,不要放进信仰里看。
07设备上有三种时间
设备上至少有三种时间。混用就会写出「事件发生在开机之前」这种故事。
- 单调钟:量间隔、做超时、决定看门狗。它不该被校时打断。
- 墙钟:写给人和云的时间戳。它会被 NTP、手动修改和时区带着跳。
- RTC:断电之后墙钟还在不在。纽扣电池是会耗尽的零件,不是背景设定。
要单独处理的情况:开机后还是 1970 年;校时瞬间时间往回跳;用墙钟切分的日志和录像被切出一段洞;多台设备谁先谁后。没有可靠的公共时钟时,用设备内单调序号表达因果,墙钟只作注释,并在上报里标明时间是否可信。
校时源可以是 NTP、要更准的工业网里的 PTP、GNSS,或由网关代授。源失败时,服务继续用单调钟工作,不要因为对时失败就拒绝完成本地职责。
08朝现场:南向
南向就是朝下这一侧:传感器、执行器、摄像机、产线总线。协议只是表面,语义才是坑。串口私有协议、Modbus、CAN、OPC UA、ONVIF、GB28181、BLE、Zigbee、专有 USB,每一种都要单独问:
- 字节序、校验、粘包、半包。校验失败的帧丢掉,不要把噪声解析成命令。
- 超时之后重发、跳过,还是进入安全态。
- 地址和拓扑会不会在现场被改掉。
- 同一条总线或同一个设备节点被两个进程打开会怎样。
- 采样率是设备的能力,不是配置文件里的愿望。
读进来的值要有「卡住了怎么发现」:范围、变化率、超时未更新。写出去的动作要有「失去心跳之后怎么办」。这一侧的超时和重连是主路径。振动和接触不良会让它们在现场变成日常,而不是异常分支。
09朝云端:北向
北向就是朝上这一侧:云、区域网关,或局域网里看页面的人。设备在下面,对方在上面。多数设备没有公网入站,所以通常是设备自己往上开口,而不是等云来敲门。
- MQTT 适合遥测、命令、遗嘱和保留消息。QoS 1 仍会重复,业务要幂等。QoS 不是可靠性的同义词。
- HTTPS 适合拉配置、传文件、给人看的 API。请求要短,失败要能重试。
- gRPC 一类的二进制 RPC 在内部契约清楚时省流量。中间盒、现场抓包和旧设备是否吃得消,要另算。
- WebSocket 适合长连接交互。断线重连要退避,还要加抖动,避免千台设备同一秒回来。
- 更小的设备和 UDP 环境里,CoAP 往往比一套 HTTP 栈诚实。
无论哪一种,都要有认证、心跳、退避、离线缓存上限和优先级。命令和遥测分开,避免一次大遥测堵住「立刻停」。入站如果真的需要,做成默认关闭、有期限、有记录的隧道。不要做成永远开着的远程登录口。
10进程之间那一截
本机协作比上网简单,也更容易写出隐式耦合。还没拆进程时就是函数调用。拆开之后是 Unix 套接字、D-Bus、共享内存、管道、本地队列或文件落地。
能用明确消息,就不要约定「我知道你把结果写在那个目录」。共享内存要有主人:谁创建,谁销毁,崩溃后谁清理。本机接口也要版本,因为邻居进程明年会单独升级。不要把跟云说话的那套协议再绕回本机调用一圈,除非你是有意让外部和内部走同一套契约。
11数据留在哪
每一种数据先问四句:谁生产,谁消费,丢了会怎样,留多久。
- 只活在内存里的:最新帧、当前姿态。重启即失,这是特性。
- 要熬过重启的:还没发出去的事件、校准、本地账号、最后一次成功生效的配置。
- 要给云的:事件、聚合、抽样。不是默认的全量原始流。
- 要给人查的:近期日志,和一份诊断包。
- 绝不能只留在一台设备上的:用户不可再生的账。设备会丢、会寄修、会被重置。
很多设备用 SQLite 就够。要控制写放大:事务别太碎,WAL 要有检查点,别让日志和数据库抢同一块已经很累的闪存。环形缓冲适合「只关心最近」。大块媒体用文件,但要有上限和清理,不要指望有人会来删。
结构会变。旧库在现场,迁不了就启动失败,等于变砖。迁移要能从空库、从上一版、从「写到一半掉电」三种状态起来。
12离线之后,同步怎么不说谎
网络恢复不是把文件夹拷上去。
- 顺序:有的事件必须按序,有的可以跳,有的过期了就该丢。
- 幂等:同一条至少会到一次。云端用设备内序号或幂等键去重。
- 容量:断网一周之后,是覆盖最旧、丢掉最低优先级,还是停采集。盘满之前就要选好,不能等内核替你选。
- 冲突:本地有人改了配置,云也下发了配置。以谁为准,冲突时两边的证据留在哪。
- 公平:一台设备不要在恢复联网的瞬间打满上行,把同一站点的别人饿死。
「恰好一次」在这一侧基本是空话。把系统设计成「至少一次,加上幂等」,然后把幂等键写进契约。先降采样、抽关键帧、传差值,再考虑原始文件。墙钟不可信时,序号表达因果,时间戳只是注释。
{
"device_id": "edge-7f3a",
"seq": 184422,
"idempotency_key": "7f3a-184422",
"wall_time": "2026-09-28T14:06:11+08:00",
"wall_trusted": false,
"kind": "event",
"priority": "alarm"
}
13来不及的时候,丢掉谁
摄像头可以每秒 30 帧,模型只能跑 8 帧,往云上送的那条通道只容得下每秒一条事件。中间一定有人被丢掉。丢弃策略是产品决策,不是实现细节:
- 留最新:交互、跟踪、控制。旧的已经没用。
- 留每 N 个:均匀抽样,适合统计。
- 留高优先级:报警不丢,普通心跳可丢。
- 积压到上限后拒绝新的:适合不能丢的命令,同时必须让生产者知道被拒绝了。
队列没有上限,就不是队列,是泄漏。每一级都要有长度、超时和「满了之后的语义」。背压要传到源头:推理忙时,采集侧降帧,而不是在内存里堆帧直到被杀死。
14当服务要看、要听、要算
感知管道通常是采集、预处理、推理、后处理,然后是动作或事件。每一段都可以单独失败。
- 采集:设备节点会变,格式会变,第一帧会特别慢。
- 预处理:缩放、色彩、重采样。旁边有硬件单元时,不要在用户态用意外的方式把 CPU 打满。
- 推理:模型多大,量化没有,跑在 CPU 还是 NPU。热了会降频,延迟不是常数。
- 换模型:旧请求还在时有没有双份内存;换失败能否留在旧模型上。
- 后处理:阈值、跟踪、去抖。阈值是业务,不要焊死在某个离线脚本里。
能在设备上变成「有人进入」就不要上传脸。保留期限写进清理任务,而不是写进愿望。音视频还要面对硬件编解码、时间戳、音画对齐、切片和断流重连。用现成的管道框架,还是自己拉,取决于现场有没有人读得懂那张图。
15资源配额:别让旁路饿死主路
控制、采集、推理、上传、日志、现场网页会互相抢。没有配额时,表现是「偶尔卡一下」,原因可能是日志压缩刚好和推理叠在一起。
用 cgroup 或等价物写下限:内存上限到了就杀死该杀的那个,而不是随机杀;CPU 和 IO 给控制回路更高的权重,日志和上传做背景。磁盘也要配额,一份跑飞的转储不应占满系统分区。内存泄漏在有交换的服务器上是慢性病,在没有交换的设备上是猝死。常驻曲线要比功能测试更早设门槛。
16闪存会老,电会突然没
闪存有擦写寿命。日志每秒刷、数据库每条事务都同步、把调试信息写上盘,都是在花寿命。你以为写了 1KB,控制器可能擦了一整个块。
掉电会发生在任何一次写的中途。所以系统分区只读;数据分区上先写临时文件,同步,再改名;数据库用它承诺过掉电安全的模式,不要为了快关掉同步。升级在任意时刻断电,起来的仍应是完整的旧版或完整的新版。只读压缩根加单独的数据分区,是设备上很常见的组合。掉电后的修复要自动做完,不能停在一个需要人接显示器的检查程序上。
17启动、崩溃、看门狗
上电路径要短,也要可预测:内核、只读根、数据分区、时间、网络、服务。某一步失败时,设备进入一个能被看懂的状态,而不是黑屏重试到发烫。
- 重启要退避,避免重启风暴把现场变成一闪一闪的灯。
- 连续失败若干次后进入安全模式:停掉非必要功能,留下诊断,并允许回到上一版。
- 硬件看门狗由独立于业务的小进程喂。业务假死时它停喂。
- 把上次为什么死留下来:退出码、最后若干行日志,能留的话再加一份小的转储。下次启动先读它。
启动依赖不要绕成环。网络不该是启动的前提,除非这个服务离开网络就没有任何本地职责。
18配置的三种真相
出厂默认,是刷机时就有的,重置能回到这里。期望配置,是云或本地管理端希望它成为的样子。实际生效,是设备此刻真的在用的,可能因为离线、校验失败或硬件不支持,和期望不同。
三种都要能被看见。只显示期望,现场会说「我明明改了」。只显示本地文件,云会说「我已经下发了」。校验失败就拒绝,并保持旧的。密钥不进普通配置,不进镜像,不进日志。本地应急修改和云端下发谁优先,改完是热生效还是要重启,都写下来。
19身份、密钥与攻击面
每台设备要有自己的身份,而不是全型号共用一个口令。产线注入密钥或证书,私钥放进安全元件,或至少放进权限收紧的存储。它要能轮换,能作废,并且生成之后不能再被导出。
通信做双向认证:云认得这台设备,设备也认得自己在跟谁说话,避免被同一网段里的假服务器领走。
攻击面按「摸得到」来想,因为边缘设备就是摸得到的。调试串口、远程登录、ADB、JTAG、默认口令、开着的管理页、未签名的 U 盘升级、能从拆下来的存储里直接读出的密钥、诊断包里的令牌、说不清来源的依赖。安全启动和签名校验解决「跑起来的是不是我们发的」。它不消灭业务逻辑里的洞,但没有它,后面的更新没有根。
物理接触下的防护有上限。写清楚哪些东西拆机就能拿走,哪些就算拆机也拿不走。拿不走的放进安全元件。拿走也无妨的,不要假装它是秘密。
20出厂之前,服务已经开始
生命周期从产线开始,不是从用户开机开始。
- 烧录:谁烧的,哪一版,板子修订号是多少。
- 注钥:密钥何时生成。如果还能再导出,量产之后就没有设备身份。
- 校准:摄像头、传感器、触摸。校准数据跟设备走,不跟镜像走。升级不能把它抹掉。
- 产测:朝下的现场通不通,朝上能不能报到测试环境,看门狗动不动。失败要分得出是板子还是软件。
- 出货切换:测试云的地址和测试用的万能密钥不能留在出货镜像里。
重置和返修要有路径:清掉用户数据,保留或重新注入身份。返修机不该带着上一个客户的数据回到仓库。
21更新弄不好,一批设备一起变砖
OTA 比加一个功能更容易把机器刷死。签名、槽位、回滚要单独留时间,别写在发布说明的最后一行。
- 设备只接受验得过签名的包。验不过就保持原样。
- 用 A/B 槽或等价方案。新系统自己证明健康:能启动、关键自检过、该连的能连上,才算提交。否则切回旧槽。
- 任意时刻断电,起来的仍是完整的一边。
- 差分省流量,差分失败要能退回全量。
- 窗口期内,新服务配旧系统、旧服务配新配置,都要能跑。不要要求所有设备今晚同时成功。
- 按批次放量。看崩溃率、回滚率、失联率,再继续。
- 电不够、网不够、或对方正在使用时,推迟。安全修补若必须立刻重启,把这个代价写进决定里。
- 每台报告当前槽位、目标版本和失败原因。没有这张表,就是在黑暗里全量发布。
还有一件容易漏:更新程序自己怎么更新。它坏了,后面所有修复都到不了。它要小,要稳,要少改。
22磁盘很小,日志不能照搬云上的做法
日志、指标、追踪按云上的密度打开,eMMC 会先被写满。设备上少留一点,但崩溃前的最后几行一定要在。
- 日志有级别、轮转和字节上限。崩溃前的最后若干行一定留下。调试日志默认关,打开了也要会自己关上。
- 指标个数少,标签更少。标签里放用户内容或无界的标识,基数会先把上报自己打爆。
- 健康要分清「进程还在」和「业务能用」。一个空转的循环也会对健康检查说真。
- 全链路追踪默认不做。需要时对单台、短时间打开。
- 可以拉取日志,不要默认把全部日志实时打到云上。
时间不准时,日志里同时留下单调钟和墙钟,不然一次重启前后的故事对不齐。
23现场要能修,门不要常开
现场的人常常不是写这个服务的人。给他的应该是一眼能懂的状态:在跑、在升级、在等网、在安全模式。灯的含义写在机身上或手册里。再加一键诊断包:版本、硬件修订、磁盘、最近日志、配置是否生效、网络能不能解析。里面没有密钥,也没有用户的原始视频。
远程支持可以有,但是经同意、有期限、有记录,到期自己关。不要留下全型号共用的口令、贴纸上的密码、永远开着的调试口,或一个「临时」但会进出货镜像的账号。临时入口一旦能把工作做完,就会活过产品本身。
24到了一万台,有些算法会变
一台设备上试通的事,铺到一片现场之后,行为会变。
- 云一抖动,所有设备若用同一条退避曲线,会一起回来把云打躺。退避加抖动。
- 现场永远同时存在着多个版本。服务端和配置要容忍,不要假设「都已经升完了」。
- 每台有期望态和报告态。差在哪里,是队列里的工作,不是群聊里的猜测。
- 发布和配置按型号、批次、地区、客户分组,而不是一刀切。
- 设备不在线时,命令要排队,也要过期。过期的重启不该在一周后突然执行。
- 上报频率乘以台数就是账单。先在纸上乘一次。
- 写清多久没报告算失联,失联时本地继续做什么,恢复后补什么、不补什么。
25已经卖出去的接口,还得继续认
接口一旦装进已出货的设备,就要服务到那一批退役。朝云的接口、朝现场的接口,还有配置,都要有版本。只加字段,不改旧字段的意思。设备忽略自己不认识的字段,云也忽略自己不认识的旧字段。新配置项在旧版本上要有明确的默认行为。
不要用「强制全员升级」代替兼容,除非你真的控制每一台,并且失败了有人能上门。在仓库里留一张表:仍在现场的最老版本能做什么。人会换,表还在。
26构建:在我机器上是好的不算数
设备上的二进制往往不是在设备上编的。交叉编译、sysroot、依赖的目标架构,任何一处偏了,就会出现编译机能跑、拷过去就段错误。
同一提交应产出可对应的制品。制品带版本、源代码修订、构建时间和目标硬件,并且签名。依赖固定。设备启动时不去公网拉一段脚本。发布物要能回答:这是哪一版,给哪块板,和上一版差在哪,回滚包在哪。答不上来的,不要进舰队。
调试符号、多余服务、宽松权限用构建开关隔开,默认不进出货配置。发布前用一份清单核对,而不是靠记得。
27测试:没有板子,和只有一块板子
每一层都要承认自己覆盖不到的东西。
- 开发机上测纯逻辑:协议解析、去重、丢弃策略、配置校验。
- 用假的硬件接口做集成:传感器给固定帧,云给假的端点。
- 真机覆盖驱动、性能、热、掉电和升级。这一层慢、贵、少,只留给下面替代不了的问题。
- 浸泡一夜到一周,看内存、温度和磁盘曲线,而不是只看功能点过了没有。
- 虐待:断网、写满磁盘、把时间拨回 1970、升级到一半断电、连续重启、喂坏数据。
- 留一小批和出货修订一致的金机。板子换了,就不算同一套测试。
开发机上的测试覆盖不了驱动和掉电。只拿一块开发板测,也覆盖不了量产时换过的那颗料。
28合规会写进代码
按这台设备实际会碰到的来写。名词堆全,代码里却没有删除和保留期限,等于没做。
- 若采集人脸、声音或行踪:最小化、目的、保留期和删除路径要在服务里有实现,而不是只写在政策里。
- 无线电和电气安规会限制功率、天线和外壳,间接限制软件能不能随意打开射频。
- 工业场景会问分区、最小权限、远程访问是否可审计,以及更新链和账户体系。
- 失败会伤人的控制,要单独的安全论证。「我们会重启」不够。
- 出货后要有组件清单,要能在合理时间内发出修补,修补到不了时要有缓解。十年后上游可能已经不管那一版系统了,这要在选底座时就知道。
合规决定数据能不能采集、远程入口能不能留、日志里能不能出现某些字段。它不是发布前一周贴上去的章。
29热、电、灰、振
实验室是二十五度、电源稳定、网线插好。现场不是。
- 温度上来就降频,推理变慢。看门狗若按实验室的超时,会误咬。超时按最坏情况留余量,或者随温度改变策略。
- 电压跌落、PoE 功率不够、电池末端:写盘和升级这种大事要先看电够不够。
- 灰尘和封闭盒子会让散热失效。软件能做的是少做无用功,过热时降载,而不是硬扛到死机。
- 振动让连接器间歇断开。重连是主路径。
- 电磁干扰让串口出现怪字节。校验失败就丢帧。
对电池设备,功耗就是产品:谁能唤醒,醒来做什么,做完能否回去。一个「顺便」的轮询可以把续航从月变成天。
30变体、SKU 与十年
同一份服务会遇见不同传感器、有无 NPU、不同大小的盘、不同客户的云地址、不同地区的射频限制。用硬件修订和运行时探测,不要复制出四份仓库。没有那颗设备、那颗 NPU、那个分区,就降级并报告原因。
十年要单独想一次。证书有效期不要短过你不愿上门更换的周期,或者把续期做进跟云通信的那条通道里。上游会消失,所以制品和构建环境要能存档。写文档的人会离开,所以「为什么根分区只读、为什么这条队列只留最新」要写在仓库里。停产之后现场的设备还在,服务端不能在某一天突然不认识它们。
31失败会以哪些样子到来
下面这些现场都会遇到。每条最好说得清三件事:平时怎么避免,出了从哪看出来,设备自己怎么回到能用的状态。
- 盘满日志先停,数据库接着报错,服务看起来只是卡住。
- 时间回到 1970证书「尚未生效」,TLS 全部失败。
- 证书同一天到期一整批设备一起连不上。
- 升级停在中间起不来,又没有旧槽可回。
- 慢泄漏第三天凌晨被杀死,重启后又像正常。
- 重启风暴现场和云同时被打满。
- 队列没有顶网络一断,内存先死。
- 现场侧卡住摄像头或传感器已经不动了,健康检查仍说一切正常,因为它没看业务。
- NPU 悄悄退回 CPU温度和延迟一起变坏。
- 配置校验没过设备沿用旧行为,云显示下发成功。
- 两个进程抢一个串口有时能开,有时不能,像接触不良。
- 校时切开日志事故前后对出一段空白。
- 看门狗喂在业务线程上死锁之后灯还在闪。
- 诊断包带出密钥或画面一次排障变成一次泄露。
- 返修机带旧数据上一个客户跟着设备回到仓库。
- 同一秒重连恢复供电的那个早晨,云先倒下。
- 节点名随批次变化服务找不到设备,被当成施工问题。
32谁在三年后还能修它
软件会比写它的人长寿。要留下不用读代码也能看见的期望态和实际态,留下版本、硬件修订和最近一次升级结果,留下一份不依赖作者的诊断路径。也留下当时的决定:为什么不拆成一群服务,为什么根分区只读,为什么这条队列只留最新。
备件和返修流程里写明软件该擦掉什么、该保留什么。现场事故、舰队、更新包的签发,最好能看成三件事。即使今天是同一个人,也写成三个职责。请假之后,钥匙不该只存在于记忆里。
33一张放哪的决策卡
| 这件事 | 更适合留在设备 | 更适合放在云或上层 |
|---|---|---|
| 毫秒到百毫秒内必须完成的动作 | 留下,并定义失败时的安全输出 | 只做建议,不把动作的唯一开关放在往返之外 |
| 原始音视频、点云、高频采样 | 本地处理,上传结论或抽样 | 只在确有必要、并且带宽和权限都允许时保存原始 |
| 全局调度、跨设备账本 | 不要把唯一副本放在某一块板子上 | 权威放在上层,设备只保留执行所需的缓存 |
| 训练和大模型的重计算 | 跑已经装得下的推理 | 训练和装不下的计算放上层 |
| 断网也必须完成的职责 | 这是它留在设备上的理由 | 恢复之后再对齐,不作为当时的前提 |
| 要经常改、设备又很多的规则 | 执行和兜底留在设备 | 编辑、审计和分发放上层 |
| 身份 | 设备自己的密钥留在设备里 | 账户、权限和组织的权威留在上层 |
靠近物理和离线的,留下。靠近全局和权威的,上去。两边都想要的,把结论和事件送上去,把原始和动作留下。
34发散之后,收回来
上面铺得比较开,动手时不用一起做完。下面六件如果还空着,上线后通常会用最麻烦的办法补上。
- 这台设备离线时,必须还能完成的一件事是什么。
- 内存、盘和每天允许写入的数字是多少。
- 身份在产线如何注入,私钥还能不能导出。
- 升级到一半断电,起来的是哪一版。
- 队列满了,丢掉谁。
- 三年后,不是作者的人怎样知道它现在到底在跑什么。