上周三晚上十一点四十,我刚洗完澡准备刷两集剧就睡,手机连续震了七八下。群里炸了——客户那边投放系统挂了,所有广告计划全部无法拉取,数据归零。我当时还裹着浴巾,头发滴着水,看了一眼电脑上挂着的监控面板,CPU使用率99.8%,磁盘队列长度直接飙到30以上。第一反应是重启,但重启按钮按下去之后,整个管理后台都连不上了,连SSH都拒绝连接。那瞬间我脑子里闪过一个念头:完了,这次不是重启能解决的。
其实这个隐患上周五就出现过,当时磁盘占用到了85%,我看了眼觉得还能撑,就没清理日志。同事老张当时还提醒我说要不要做个定时清理脚本,我说没事,周末访问量低,周一人少了再处理。结果周一人是少了,但日志没少。到了周三晚上,广告投放引擎要跑批量数据,直接就把那点剩余空间吃满了。更蠢的是,我们那台服务器是单机部署,没有做负载均衡,备份任务虽然写了,但不检查日志,上次成功备份其实已经是十二天前的事了。我以为它每天在跑,实际上第三天就报错了,因为备份目录权限被我改错了,之后一直静默失败。
我一边用手机热点连另外一台测试机查日志,一边给同事打电话。运维岗的小周接电话时明显刚睡着,声音都糊的。他听我描述了现象之后,第一句话问的是:你动过什么配置吗?我当时挺烦,说我能动什么,我就跟平常一样。但挂完电话我冷静下来,翻了一下自己的操作记录——周二下午为了调一个接口的响应速度,我把nginx的worker_processes从4改成2,还改了一个超时参数。我没测,觉得改动很小不会有影响。结果那个接口本来就是阻塞式的,改完超时之后,请求全卡在队列里,再加上日志疯长,把内存也拖崩了。那一刻我特别羞愧,这根本不是突发事件,是我亲手埋了一颗雷,然后等了48小时踩响它。
第二天早上客户方负责人发来一段很长的话,大意是说我们的技术能力让他们感到不安,要求我们出书面说明。我当时准备了一堆解释,比如流量峰值超出预期、第三方接口不稳定之类的,但最后删掉了,我写了一段话:这次故障百分之百是内部原因,磁盘、内存、配置、备份全踩雷,预计两小时内恢复,恢复后我会交付一份完整的现状清单和整改计划。说实话,写到这里的时候我想起去年我在上一家公司,也遇到过类似的事,那次是数据库主从延迟,我直接在群里甩锅给云厂商,结果后来查出来是自己在凌晨两点跑了一个全表扫描的报表。两次对比,我发现一个规律:我越是愿意承认自己偷懒,后续的补救反而越顺利。因为当你承认了,你的同事和领导才有可能帮你一起补漏,而不是花时间分辨到底是谁的责任。
从这次事情里我总结出三个以前我绝对不想承认的事实。第一,突发状况是你平时所有侥幸的叠加,不是运气问题。我算了算,如果上周五我花十五分钟清理日志,周二改配置后跑一遍压测,周三晚上可能根本没有任何异常。但我选了最省事的路,结果花了两天时间收拾残局。第二,所谓应急预案,不应该是一份挂在wiki里的文档,而应该是一系列你真心认为会用到、并且实际验证过能跑的脚本和权限。我们其实有预案文档,但里面写的是联系某某负责人,这个人已经离职三个月了;预案里说备份存放于某云盘,但那个云盘的账号密码在另一台同事的电脑里,同事出差了。第三,突发状况反而是看一个人真实工作水平的最佳窗口,因为平时你有同事提醒、有领导兜底、有模板套用,但真到了凌晨十一点四十,所有遮羞布都会飘起来。我见过平时看起来很厉害的人在宕机时只会点重启,也见过平时话很少的实习生默默把所有服务器的SSH别名和密码写在本地笔记里,还设置了每周校验一次备份是否可恢复。
后来我花了大概三小时把服务器恢复了,首先是释放空间——删掉了接近40GB的日志文件,再把nginx配置改回原来的参数,重启进程,让积压的请求慢慢消化。接着检查备份,发现那个静默失败的问题后,我马上写了一个简单的shell脚本,每次备份完成后自动比对文件数量和总大小,如果跟上次不一致就发钉钉告警到群里,并加了cron任务每天早上八点跑一次。那个脚本核心就三行,加上判断逻辑也不到十五行,我原来觉得写这种东西无聊透顶,但那天晚上我看到它成功执行,打印出"backup ok, total 8.7GB"的时候,竟然有点想哭。我又把所有需要定期检查的指标做成了一个表格,每行写了检查项、阈值、检查频率、上次检查人、上次检查日期和下次计划日期。第一行就是磁盘使用率,阈值85%,频率每天。我填上日期的时候忽然觉得,这才是真正的工作,不是出问题的时候表现得多英勇,而是在没问题的时候就让自己看上去像个多管闲事的讨厌鬼。
如果你现在也正在为某个"突发状况"焦头烂额,我只想跟你说一句:别急着怪别人,也别急着怪环境。你先把时间线拉出来,把每个关键决策点标出来,看看那些时刻你是在敷衍还是认真。我敢打赌,大部分所谓突发,都是你自己一步一步精心设计出来的。承认这一点很痛,但你一旦承认了,你就不再需要靠运气去混日子了。