脚本自愈的边界:哪些故障可以自动重启

去年冬天一个周六凌晨两点,核心交换机的辅助进程挂了,级联影响到三套业务系统。值班手机响的时候我已经在被窝里睡了一个半小时。爬起来、连 VPN、敲三条命令、重启进程、确认恢复,全程十八分钟。那晚之后我认真想了一件事:这三条命令,能不能不等人来敲?

这就是脚本自愈的起点。现在我们内网有三十九个自动恢复点在运行,覆盖进程守护、服务重启、缓存清理、磁盘空间释放四类场景,一年下来自动处置了两百六十多次异常,真正需要人爬起来的夜间故障从平均每月五次降到一次以内。但这篇的重点不是吹自愈多好用,而是讲它的边界——哪些故障可以放心交给脚本,哪些宁可半夜叫醒人也不能让机器自己动手。边界划错了,自愈系统会比故障本身更危险。

一、自愈的资格线

1.1 三问定资格

一个故障场景要不要上自动恢复,我们立了三问。头一问:恢复动作是否可重复——同样的故障,任何人来处置,动作是不是都一样?第二问:误判后果是否可承受——如果这其实不是故障、或不是这种故障,执行了恢复动作,最坏会怎样?第三问:恢复是否时间敏感——等十分钟等人来处理,业务是否能接受?

三问全过才有资格上线自愈。进程挂了重启,动作可重复、误判重启一次损失有限、时间敏感,全过。数据库主从延迟,处置动作取决于延迟原因,不可重复,不过,必须人看。就这么简单粗暴,但有效。

1.2 头一批要保守

头一批上线的只有六个恢复点,全是"重启即恢复"的成熟场景,跑了两个月零误动作,才敢往第二批扩。见过同行一上来铺几十个恢复点,第三天一个误判把生产库的从库重启了,延迟雪崩,从此整个自愈项目被毙。自愈系统的信誉是一次一次正确动作攒出来的,一次大误判就够清零。慢就是快。

二、四类放行场景与动作设计

2.1 进程守护类

最典型的是那些老应用的自带辅助进程:内存泄漏跑到阈值就挂,挂了业务就断。恢复动作是检测到进程消失后先收尸(拉核心日志尾部)、再拉起、再验证端口。验证这一步不能省:拉起来不代表好了,端口不通就说明恢复失败,立刻升级告警而不是反复拉起。

#!/bin/bash
PROC="legacy-agent"
PORT=8123
LOG=/var/log/selfheal.log

if ! pgrep -x "$PROC" >/dev/null; then
    tail -n 50 /var/log/$PROC/err.log >> $LOG   # 收尸:留现场
    systemctl restart $PROC
    sleep 8
    if ss -ltn | grep -q ":$PORT "; then
        echo "$(date '+%F %T') $PROC restarted OK" >> $LOG
    else
        echo "$(date '+%F %T') $PROC FAILED after restart" >> $LOG
        alert_escalate "$PROC 恢复失败,需人工介入"   # 升级,不重试
    fi
fi

这段脚本的灵魂是最后那个分支:恢复失败必须升级而不是循环重试。无限重试的自愈等于自动攻击自己,我们把单点恢复次数限制在一次,失败即告警叫人。

2.2 服务重启类

IIS 应用池假死、Java 服务线程池打满,这类故障重启即恢复,但重启有连接代价,所以动作设计里加了两个前置:摘流量、等排空,再重启,再挂回流量。重启窗口控制在九十秒内,业务侧基本无感。

2.3 空间清理类

磁盘空间告警是最适合自愈的场景:清理日志归档、清空回收目录、压缩老文件。但白名单机制是铁律——只删"明确可再生"的路径,日志归档目录、临时目录、缓存目录,白名单之外的路径,脚本碰都不能碰。曾经有同行图省事写了 find 按天数全局清理,误删了数据库上传目录,数据丢了三天。这个教训我记了十年,白名单三个字值一顿血泪。

2.4 缓存刷新类

缓存与源不一致引发的页面异常,刷新 CDN 或本地缓存即恢复。这类动作业务无破坏性,但频率要限制:同一路径一小时内最多刷两次,超过说明根因不在缓存,刷烂了也没用,升级处理。

三、不放行的四类

3.1 数据类故障

数据库无响应、主从切换、数据不一致,永远人工。原因不是脚本做不了切换,是切换的决策依赖太多上下文:延迟原因、业务时段、备份状态、是否连锁故障。脚本只看得见指标,看不见这些。数据是企业的命根子,命根子上的操作,决策权必须留给人。

3.2 连锁故障

监控大面积告警时,禁用一切自愈动作。连锁故障的表象会骗人:A 故障引发 B C D 告警,自愈系统忙着重启 B C D,既掩盖了真凶 A,重启动作本身还在给已经脆弱的环境加压。我们的联动规则:同一机房十五分钟内告警超过二十条,自愈全局熔断,只告警不动作,等人来。

3.3 不明原因的性能劣化

CPU 高、响应慢,原因可能是流量、可能是攻击、可能是自身 bug。这类"症状型"故障没有可重复的恢复动作,硬要自愈只能瞎重启,重启可能暂时压下症状,但每次重启都是一次现场销毁,性能问题的根因永远查不出来。性能问题要的是观测,不是动作。

3.4 涉及资金与对外承诺的动作

任何会向外发数据、触发资金动作、影响客户承诺的操作,不在自愈范围。这条不解释,解释权在审计。

四类禁区划下来,能自愈的场景看着少了不少,有同事觉得可惜。我倒觉得这份"可惜"恰恰是安全感:禁区越多,故线之内越敢放手动。边界不是限制自海的,边界是解放自海的。

四、自愈系统的自我修养

4.1 每次动作必须留痕

三十九个恢复点,每一次触发都记录五要素:触发时间、触发指标、执行动作、执行结果、当时的指标快照。每月复盘一次全部动作记录,误动作率目标是零——达不到就收紧阈值。自愈系统的日志比业务日志还重要,它是你敢继续信任这套系统的唯一依据。

4.2 演练不能少

每季度做一次故障演练:人为制造三类放行场景的故障,验证自愈链路活着。有次演练发现某个恢复点引用的路径变了,脚本一直静默失败——幸亏是演练发现的,不是真故障时发现的。自愈系统自己也会烂,它也需要被巡检。

4.3 人的角色:从操作者到立法者

一年下来最大的体会:我的工作从"处置故障"变成了"制定处置规则"。半夜的手机还是会响,但响的次数少了八成,而且响起来的一般是真需要判断力的事。自愈没有消灭运维,它把运维从肌肉劳动里捞出来,去干更值钱的事:划边界、立规则、查根因。

还有个意想不到的变化在团队里:新来的运维不用再把半夜应急处置手册背得滚瓜烂熟,三十九条规则就在系统里,规则后面还挂着当年的事故记录和讨论纪要。自愈系统顺手成了培训教材,新人读懂了边界在哪,也就读懂了这个岗位一半的本质。

常见问题

问:自愈动作失败后为什么不自动重试多次?

答:失败说明问题超出脚本的理解范围,重试是在未知领域反复押注。我们的设计是一次失败立即升级,把决策交还给人。宁可半夜叫醒工程师,不让机器在黑暗里独自尝试。信任是有额度的,别让脚本透支。

问:怎么判断自愈阈值,避免频繁误触发?

答:阈值宁松勿紧。自愈触发条件用"持续时长加指标双确认":指标越限且持续五分钟才动作,瞬时毛刺直接忽略。上线前拿历史监控数据回放,算一遍这套阈值下过去一年会触发多少次、其中多少次是真故障。回放这个步骤没做过就上线,等于闭着眼睛开枪。我们有一台老设备的内存指标天生爱抖,回放发现它一年会换四次误触发,单独给它把持续时长加到十分钟,误报清零——阈值允许按设备特例,也是回放教会我们的。

问:领导要求所有告警都自动处置怎么办?

答:拿三问资格线顶回去,尤其是误判后果那一问。给领导看两个账:一次误处置的业务损失账,和一次人工半夜响应的响应时长账,两本账摆在一起,边界应该划在哪,通常不难谈。全都自动处置的诉求,本质是把判断责任甩给机器,出了事没人能负责。

问:这套和智能运维是一回事吗?

答:自愈是智能运维里最皮实的一块,规则明确、动作有限、结果可验证,所以适合先做。但它只是起点:真正的智能运维还要在故障预测、根因定位上铺开,那些方向不确定性高得多。我的建议永远是先把自愈这块硬骨头啃了——它攒下的动作记录和边界框架,正是后续智能化最值钱的养料。

posted @ 2026-10-31 14:16  离线漫游中  阅读(3)  评论(0)    收藏  举报