周五下午,吉彤正在调试一个动画性能优化,企业微信群里突然弹出孙姐的一条消息,语气比平时急了几分:“登录模块线上出现了大量超时报错,谁在关注?”
吉彤刷新了一下自己的测试环境,没有异常。他切到生产环境的监控面板,红色的报错曲线从十四点二十分开始陡然攀升,到此刻已经翻了三倍。报错类型集中在验证码接口的超时——用户提交手机号之后,等待验证码的时间超过了预设的十秒阈值,前端自动触发了重试,但重试的失败率也高得异常。
“我刚看了日志,”沈瑶的声音从工位那头传过来,“华信那边今天下午做了一个网关迁移,可能改了验证码服务的路由策略。咱们这边的请求被重新路由到了一个新的实例,但那个实例的限流配置跟之前不一样。”
吉彤翻出之前跟华信联调时整理的接口配置表,迅速比对了一下。他发现在网关迁移之后,原本每分钟三次的限流降到了每分钟一次,再加上午后使用高峰期涌入的请求,新的实例被瞬间打满,大量请求在队列中排队超时。
“孙姐,我查到了,”吉彤快速打字,“限流阈值被改回去了,降到了每分钟一次。请求高峰叠加上超时重试的放大效应,现在的失败率在35%左右。”
孙姐在群里回了一句:“吉彤联系华信那边确认限流配置,沈瑶准备前端降级方案,如果五分钟内恢复不了,我们把验证码入口暂时切换成短信下发提示,先止血。”
吉彤拨通了小张的电话。响了一声就被接起来,小张的声音明显有些紧绷:“我知道了,网关迁移的时候配置没同步,我正在回滚限流参数。”
“回滚大概多久生效?”
“三到五分钟。我先把阈值提到每分钟五次,给咱们留足缓冲。”
“好。前端这边我会做两件事——第一,重试间隔从两秒调整到三秒,避免重试风暴;第二,如果连续两次重试失败,不再自动重试,而是显示一个手工触发的‘重新获取’按钮,让用户自己决定要不要再次请求,这样能把请求量控制在合理范围。”
小张沉默了一瞬:“你这方案反应真快。我先改配置,咱们十五分钟后同步状态。”
吉彤挂掉电话,迅速改了两行代码参数,把热修复通过公司的发布系统推到了生产环境。他盯着监控面板上的曲线,等待数据回传。第一分钟,报错曲线还在攀升;第二分钟,攀升的斜率放缓了;第三分钟,曲线开始掉头向下。
沈瑶走到他工位旁边看着屏幕:“华信那边回滚了吗?”
“正在回滚。我把重试逻辑调了,先压一压流量。”
两个人盯着监控面板没有说话。时间一分一秒过去,红色的曲线终于在第五分钟时断崖式下坠,回归到了正常的绿色区间。吉彤刷新了一下页面,验证码发送的成功率重新回到了98%以上。
孙姐在群里发了条消息:“恢复了。吉彤、沈瑶、赵宇,下周一上午十点,复盘会。”
吉彤靠回椅背,长长呼出一口气。他低头看了看时间,从报错出现到问题解决,前后一共二十三分钟。
如果是以前的公司,他想,二十三分钟可能连谁该负责都还没吵完。
赵宇从工位那边探过身子:“卧槽,刚才那二十分钟我心跳都加速了。你那个降级方案写得够快的。”
“之前联调的时候踩过限流的坑,心里有数。”
“华信那边怎么说?是他们的问题吗?”
“网关迁移配置没同步。”吉彤关上监控面板,“小张已经在改了。”
赵宇靠回椅子上,嘴里“啧啧”了两声:“要在以前公司,这会儿群里应该已经开始骂华信了。骂完华信骂网关负责人,骂完网关负责人骂测试没测全,反正不骂到有人摔键盘不罢休。”
吉彤没有反驳。他想起在恒远科技经历过一次类似的事故——第三方支付接口升级导致订单系统崩溃了四十分钟,技术群里从“谁负责的”开始,一路滑向“某某上次就说过这地方有问题你们为什么不听”,最后运维和开发在会议室里吵了整整一个下午,直到晚上十点才有人想起来先把系统修好。后来那次的复盘会也开了,但更像是划分责任界面的谈判会,每人轮流念自己提交的免责说明。
而刚才的二十三分钟里,群里最激烈的词是“止血”。没有人问“谁的责任”,所有人都在问“怎么解决”。吉彤意识到这一点的时候,觉得这个认知像一枚硬币的正面,清晰得几乎刺眼。
周一上午十点,小会议室。
吉彤到的时候,孙姐已经坐在长桌一头了,面前摊着一份打印好的时间线。沈瑶坐在孙姐右手边,赵宇坐在吉彤旁边,手里转着一支笔。会议桌上放了一壶温水,旁边摆着几个一次性纸杯,跟平常的例会差不多,氛围不像要追责的样子。
“咱们快速过一下周五的事。”孙姐在桌面上点了点那份时间线,“吉彤先把过程从头捋一遍。”
吉彤打开自己周末整理的记录,开始叙述。从十四点二十分监控触发告警,到十四点二十三分确认问题根因,到十四点二十五分联系华信,到十四点三十分前端降级方案上线,到十四点四十三分华信配置回滚完成、系统完全恢复。他把每个时间节点后面对应的决策依据也说了——为什么调整重试间隔,为什么把自动重试改成手动触发,为什么没有直接关闭验证码入口而是保留了手工按钮。
“主要原因是华信网关迁移后限流配置回退,加上前端重试机制放大了请求压力。目前的处理结果是,华信那边已经将限流阈值统一调整,并且把所有环境的生产配置做了版本化管理,以后不会再出现迁移后配置自动回退的情况。”吉彤说完合上了笔记本。
孙姐点了点头:“华信那边沟通的情况呢?”
“小张周五下午就改了,还额外在配置中心加了一道审批流程,任何限流参数变更需要有两个人确认才会生效。”
沈瑶补充了一句:“周五当天下午,华信的王总也给我发了消息,说已经内部通报了这次事故,网关迁移方案下次会提前跟我们同步。”
孙姐没有追问任何一个人的“失误”,也没有要任何人表态“下次保证不出错”。她只是拿起笔在时间线那张纸上画了几个圈:“华信那边的变更通知机制是断裂点。以后所有外部合作方的生产环境变更,都要提前至少一个工作日同步到咱们的项目群里。吉彤,你回头建一个外部变更同步的规范模板,发我审一下。”
“好。”
“另外,这次前端降级方案响应速度很好。吉彤能在五分钟内拿出热修方案,说明对系统的熟悉程度到位了。”孙姐看了一眼吉彤,又看向赵宇,“赵宇,你这次虽然没有直接参与修复,但监控告警是你配置的?第一时间触发报警的就是你那天设的阈值,提前发现了问题。”
赵宇愣了愣:“呃,那个监控是我上周顺手配的。”
“配得很好。现在说说这次的事有哪些可以优化,从技术层面复盘,不针对人。”
接下来四十分钟,几个人聊了监控告警的粒度、外部依赖降级的预设方案、以及如何跟华信那边建立更自动化的配置同步机制。吉彤发现自己在笔记本上记了七八条改进点,其中有三条是他自己提出的——包括预设一份“外部服务异常时的前端降级预案手册”,把可能出现的各种故障场景按优先级列好,省得到时候临时想方案。
快结束的时候,沈瑶放下笔说:“我补充一个问题。周五的告警虽然触发了,但最开始报出来的信息不够精确——登录模块超时报错太宽了,我花了三分钟才确认是验证码接口而不是登录接口。建议以后告警信息里直接带上接口路径和错误码段,能缩短定位时间。”
孙姐说:“记上。吉彤,你配合运维那边把告警规则细化一下。”
复盘会结束时刚过十一点。吉彤收拾笔记本的时候,赵宇在旁边低声说了句:“这就完了?不写事故报告?不扣绩效?”
“时间线记录和优化方案就是事故报告。”
“我的意思是,”赵宇压低嗓子,“以前公司出这种事,总得有人被拎出来负责吧?不管是华信的人还是咱们的人,总得有一个名字写进报告里,然后扣钱、降绩效、或者全组通报。刚才说话的时候我一直在等那句这件事谁要承担责任,结果一直等到散会都没听到。”
吉彤沉默了几秒。他也注意到了——孙姐全程没有问过一次“谁该负责”,她问的全是“哪些环节可以优化”。华信那边的失误被描述成“配置同步机制有缺口”,而不是“小张或刘师傅犯了错”。
“可能这就是她们说的,解决问题比划分责任重要。”吉彤说。
赵宇张了张嘴,最后说了一句:“那要是真有人故意犯了大错呢?”
“这我还没遇到过。”吉彤站起来,“但按照这里的风格,估计也是先解决问题,再聊怎么避免再犯。至于故意犯错,我觉得那就不单纯是职场问题了。”
下午两点,吉彤收到小张的微信消息。他发了一张截图,是华信内部的“对外变更通知模板”,上面填写了网关迁移的时间、影响范围、配置变更清单和紧急联系人,落款处有小张和刘师傅两个人的确认签字。小张在消息里说:“按王总要求,以后所有变更提前一天发你们群里。你看看这个格式行不行。”
吉彤放大截图看了一遍,模板做得颇为周全,比他预想的要细致。他回了一句:“行,这个很清楚了。我们这边也会同步建立内部监控规则,以后出问题定位更快。”
小张回了个拱手抱拳的表情。吉彤盯着那个表情看了两秒,觉得双方的沟通方式正在往一个中间地带靠拢。
傍晚五点半,吉彤去茶水间接水的时候碰见了林悦。她正往杯子里泡一包什么花果茶,看见他便说:“今天的复盘会我听说很顺利。”
“比我想象的顺利。没有追责。”
“本来就不该追责。”林悦把茶杯盖上,“周五的事从发现到解决不到半小时,团队反应很快。如果孙姐花半小时在会上找谁要负责任,那才是真正的浪费。”
吉彤靠在茶水台边上:“我以前的习惯是,出了问题先想‘该怎么解释’,而不是‘该怎么解决’。今天复盘会全程我都在提醒自己,这是在聊改进不是在聊免责。”
“习惯要慢慢改。”林悦拿起杯子,“但你已经在往前走了。对了,你那个降级预案手册的想法很好,回头写完了给我一份,产品那边可以帮你补用户侧的话术。”
“好。”
林悦端着茶走了。茶水间的窗户开着,傍晚的风比上周凉了一些,带着远处不知哪家烘焙店飘来的面包香气。吉彤倒了一杯热水,没有加任何茶叶,就这么端着站在窗边看了一会儿外面的街景。写字楼对面的居民楼里,有人在阳台上收衣服,动作慢悠悠的。
他喝了一口热水,把纸杯丢进回收筐,回到工位继续写那份降级预案手册。
写到第三个故障场景的时候,赵宇从旁边探过脑袋来看了一眼,说了句“你这个写得比咱们的接口文档还细”。吉彤嗯了一声没有停笔。他在脑子里把周五那二十三分钟重放了一遍,当时那种紧张但清晰的感觉,像一根绷紧的弦,每个动作都带着明确的指向性,没有犹豫也没有惊慌。那种感觉他之前在恒远从来没有过——那里出了问题只有混乱、推诿和事后算账,解决问题的行动本身反而被挤到了角落。
他把“验证码服务不可用”场景的降级方案写完,存了文档。屏幕上弹出一条企业微信消息,是孙姐在技术群里发的一句话:“今天复盘会纪要已经上传,大家有空看看。吉彤的降级预案框架很不错,后续大家可以在这个基础上补充各自负责模块的预案。”
吉彤看到自己被点名,脸上没什么表情变化,但往下翻的时候发现沈瑶在群里回了一句“我先把支付模块的补上”,赵宇也回了个“登录那边我帮忙润色一下”。
他关上电脑,收拾背包。经过赵宇工位时,看见赵宇已经在笔记本上写写画画了,嘴里念念有词地嘀咕着“支付超时、回调失败、签名校验……”像一份草拟中的预案大纲。
吉彤没有打扰他,轻手轻脚地走向电梯。经过公告墙的时候他习惯性扫了一眼,那张关于冰箱柠檬的便签已经被新的覆盖了,现在是张粉色便签,写着“本周末团建投票:漂流/密室逃脱/手工陶艺,请选择”。下面已经密密麻麻写满了正字,漂流遥遥领先。
他走进电梯,按下一层。手机震了一下,是他妈发来的消息:“最近工作怎么样?还适应吗?”
他打字:“挺适应的。今天处理了一次线上故障,挺顺利。”
发出去之后想了想,又补了一句:“跟以前不一样,这里出了事没人先怪谁,都是先想办法把问题解决了再说。”
他盯着那条消息看了几秒,觉得这大概就是最大的不同。不是有茉莉花茶或者红豆汤,不是有加湿器和毛绒玩具——而是遇到麻烦的时候,所有人的第一反应是解决问题,而不是把麻烦扔给别人。
电梯到了一层。他走出大堂,初夏的傍晚蝉鸣初起,空气温热潮湿。他穿过广场走向地铁站的时候,脑子里继续转着那份降级预案手册的框架——支付模块、推送模块、第三方登录、文件上传,每个模块都值得写一份独立的降级方案,这样下次不管哪个环节出问题,都有现成的操作手册可以翻。
他在地铁上找了个座位坐下,掏出手机打开备忘录,开始把刚才想到的模块清单列了下来。旁边座位上的人看了一眼他的屏幕,大概是看见满屏的技术术语,又收回目光去刷短视频了。
吉彤列完清单,熄屏。地铁在隧道里穿行,窗外的广告灯箱一帧一帧掠过去。他闭上眼睛靠在后背上,脑子里是今天复盘会上孙姐那种平淡而务实的语气,以及赵宇在散会时说的那句“这就完了”。他甚至觉得有点好笑——那个“完了”问出来的时候,赵宇的表情像是刚从某个困了他很多年的牢笼里走出来,站在门口回头看了一眼。
地铁到站。吉彤站起来走向车门,手机又震了一下。这次是沈瑶发的私信:“降级预案手册的框架很棒,我刚才看了个开头,逻辑很清晰。建议你下周组会时给大家讲一遍,其他人可以照着模板填自己的模块。”
吉彤站在站台上回了一句:“好,我准备一下。”
他走出地铁口的时候,天边还剩最后一抹橘红色的余晖。他沿着人行道往出租屋的方向走,路过一家小超市时停下来买了一瓶水。结账的时候他想起一件事——今天是小张发的那个变更通知模板里,落款处多了个“确认人”的栏目,跟之前在蔚蓝茶水间看到的那张“吃我请随手补货”的便签,本质上好像也没什么不同。
都是补上缺口。都是让一个系统运转得更顺畅一点。
他拧开水瓶喝了一口,继续往家走。