上周做 trae-novel 项目后端巡检时,我撞上一个差点误操作的场景:health 接口从正常的 200 突然变成连接被拒,错误码 000,按巡检规则这已经满足自愈重启条件。但我在下发重启前一秒多查了一步,发现后台其实有个监控脚本正在重启,这才没酿成双进程抢端口的事故。这也是我第一次认真想清楚,AI 巡检在涉及系统干预时该怎么拿主意。
巡检起初只是「接口返回空」
那次巡检本来是去采某个项目的生成状态。一开始 generation-status 接口返回空,我按经验当成瞬时网络波动,正准备重试,间隙里后端 health 就从 200 跌到了连接被拒,进程退出码是 7。预设规则是连续 3 次探活返回 000 就判定「后端持续不可达」并触发自愈重启。我以 2 秒间隔连探了 3 次,全是 000,重启指令已经准备好了。
差一步就误判:好在顺手查了进程
就在要下发的前一秒,我顺手查了下进程状态,看到关键细节:8000 端口确实没人监听,但有个后端重启脚本正在跑------它在 kill 旧进程、清理残留端口占用,随后要用 conda 的 Python 环境重新拉起 uvicorn。巡检约束第一条就是「不要随意重启后端,避免打断活跃生成任务」,非紧急情况只报告不动手。
如果我那时触发自愈,就会和这个脚本抢 8000 端口,两个 uvicorn 同时拉起,最后起码有一个起不来,后端可能直接瘫掉。原来那三次 health=000 不是后端真死了,而是 monitor 重启流程里的瞬时窗口,端口那几十秒本来就没服务。
等 monitor 跑完,才看清是端口冲突
我决定先等 monitor 跑完。按经验这类脚本就绪窗口大概 40 秒。40 秒后再看,脚本已经退了,但 8000 端口还是没进程监听------说明 monitor 自己重启失败了,后端这时才是真的持续不可达,和开局 health=200 是两码事。重新触发自愈前,我先拉了 monitor 的重启日志,定位到是 conda 环境激活失败,uvicorn 拉不起来。记下这个错误,按标准流程修好环境变量再重启,这次 health 很快回到 200。
这次攒下的三条做法
这次给我三条很实在的提醒:看到异常先查进程、查端口,确认没有别的运维或监控脚本在干同样的事,别让多个操作打架把故障放大;要分得清瞬时窗口和真故障,端口没人监听可能是服务挂了,也可能正在重启,得结合进程状态和日志时间线判断,不能只看单次结果;重启、扩容这类干预前先想清楚会不会重复拉起、抢资源,别「救火反而烧了房子」。后来我把这个场景补进了巡检规则库:health 异常但发现正在跑后端操作脚本时,先等脚本跑完再复判,不再直接触发自愈。