第三十九章 · 告警¶
手机在震。桌面上的震动模式——嗡——嗡——嗡——间隔不到两秒,是一批告警。
陈稳醒了。脸在手臂上压出一道印子,麻从指尖蔓延到肩膀。天没全亮,窗户外面是深灰蓝色。他趴着睡着的,不知道睡了多久。
他伸手摸到手机。屏幕亮着:
[P1] 营销补偿服务 · 重试队列深度超过阈值(当前 8,437,阈值 5,000)
营销补偿服务。蒋辉的。
他把手机放回桌面,屏幕朝下。铁的桌面放大了震动,嗡——嗡——嗡——像一个持续的追问。
他知道这条链路的每一段。蒋辉的补偿方案十一月底转交到一组共用资源池。他的消息服务十二月上旬被接入了补偿回调。死信队列的重新入队逻辑——他写过。如果队列深度继续往上走,规则引擎会在四十分钟内积压,结算系统收到延迟事件,商户端触发超时重试。两个小时之内值班群里有人@所有人。第一个@的一定是他。
手机在震。他没有动。他靠着椅背,盯着天花板。灰白色的,有一根灯管的启辉器在闪,隔两秒亮一下。
他想起昨天万钧说的那句话——「一个不会说自己做了什么的人,很难让人相信他能带别人做什么。」
还想起自己记事本里没保存的三行字。「继续做」三个字。如果答案是继续做,那老梁就是答案——他删掉了那行判断,没保存,但他记得。
他坐了一会儿。窗开了一条缝,十二月下旬的风灌进来,干的。他把窗户关上。手机又震了一下。
他拿起了手机。
四条告警。重试队列深度 11,247。响应时间 12,800 毫秒。消费者组积压 17,642 条。结算成功率 99.70%。
平时是九十九点九九。降了零点二九。
他把手机揣进口袋,打开显示器。监控台上四台 POD,三台正常,一台响应时间飙到一万三千毫秒。流量分布不均匀——正常的三台每台处理约一千二百条每分钟,异常的那台处理了四千七百条。
他打开那台异常 POD 的日志。日志窗口滚动了几秒,停在一个重复的模式上:
2026-12-21 06:12:47.381 [compensate-handler-8] WARN c.h.settle.compensate.RetryHandler - 重试回调失败,任务ID=comp_task_20261221_00084721,重试次数=1/3,CONCURRENT_LIMIT
...
2026-12-21 06:12:47.392 [compensate-handler-8] WARN c.h.settle.compensate.RetryHandler - 任务ID=comp_task_20261221_00084721 已达最大重试次数,进入死信队列
2026-12-21 06:12:47.410 [compensate-handler-8] WARN c.h.settle.compensate.DeadLetterHandler - 死信队列处理:任务ID=comp_task_20261221_00084721,重新入队补偿,延迟 5000ms
2026-12-21 06:12:52.844 [compensate-handler-9] WARN c.h.settle.compensate.RetryHandler - 重试回调失败,任务ID=comp_task_20261221_00084721,重试次数=1/3,CONCURRENT_LIMIT
死信队列把失败任务延迟五秒重新入队,根本问题没解决,重新入队的任务再次失败——循环。每秒新增六十条死信,每条走三次重试,每秒钟一百八十次无效调用,从凌晨三点十一分开始。三个小时,约两百万次。
他在终端上打了一行命令确认回调地址:
输出了一个 IP。不是服务名。
他关上终端,没有继续。
如果他修好了蒋辉的模块,纪衡问「谁处理的」,蒋辉会说「我」——主导权是对方的,他见过的模式。
手机又震了一下。第五条告警——结算成功率 99.60%。
值班群里已经有消息。自动告警「未确认,请及时响应」——系统的提示语,冷冰冰的,在白色背景上标了红色。蒋辉回了一条:「收到了。在排查。」三分钟前。
陈稳把手机翻过去。不是他的值班。不是他的模块。不是他的问题。
他把光标停在一行 TODO 注释后面,按了一下键,把 TODO 改成了 FIXME。然后关掉 IDEA,打开终端,重新连上了集群。
回调地址改服务名。八行配置,一个 sed。他先确认了 POD 环境变量里服务发现组件可用——SERVICE_DISCOVERY_ENABLED=true。可用的。不是环境问题,是部署配置写错了。
他把四台 POD 滚动重启。第一台重启完,回调地址已经变成 http://settle-compensate-svc:8080/compensate/callback。剩下三台依次替换,全程不到四分钟。
死信队列积压了大约四万二千条任务。他没有清除——那是合法的补偿请求,只是之前因为负载不均没处理成功。他修改了死信队列的重新入队延迟:从五秒改为三百秒。让 POD 先消化完当前积压的正常请求,再处理死信重投。
改完。确认。回车。
POD 响应时间从一万三千毫秒回落到三百毫秒。监控台上那条绿色的曲线从红色区域中间穿过去,头都不回地扎回了基线范围。结算成功率从 99.60% 往回升——99.65、99.72、99.81、99.92——每刷一次涨一点,像有人在一点点把落下去的线拉回来。
他把监控台最小化。然后删掉了终端历史里改配置的那两行命令——查 POD 环境变量的和改回调地址的。留下了查日志的命令。
他不知道为什么要删。可能是如果蒋辉来查,操作记录里看不到谁改的。也可能只是不想让人知道他来过。他记得二十二章那次 P0 事故——他在群里什么都没说,蒋辉主动承认了配置问题。这次不一样。这次是他主动修了,主动删了记录。主动和被动之间,差的是什么,他说不清。
六点四十三分。从他醒来到现在,约四十分钟。
他站起来。手机在口袋里。
他去了便利店,买了一瓶矿泉水和两个包子。站在门口吃完。包子是冷的,猪肉大葱馅。吃完去了一趟公司附近的公厕,洗了一把脸。对着一面镜子——眼白上有一小块红色,毛细血管破了。
回到公司楼下,七点四十三分。旋转门的门禁刷了一下,滴,通过了。
他坐回工位。监控台上结算成功率九十九点九八。他打开 IDEA,开始写今天要改的代码。
八点二十一分。脚步声从走廊那边传过来,不是一个人的。
「——排查了大概半个小时。不是代码的问题,是部署配置,回调地址配成了 IP。」
陈稳没有转头。他继续写代码。
「谁处理的?」纪衡的声音。
「我。夜里六点左右收到告警,排查到流量不均,改了配置重新部署。」
陈稳的手指悬在键盘上方,没有按下去。他听到自己删掉的那两行终端历史在脑子里回放了一遍。他知道如果这时候转头,跟纪衡对视一眼,蒋辉的话就撑不住了。但他没有。不是因为怕蒋辉。是因为他不确定自己转过这个头之后,跟蒋辉有什么区别。
「解决了?」纪衡。
「解决了。结算成功率已经恢复。」
「收到。」
脚步声继续往走廊那头走。经过他工位的时候,蒋辉的步子顿了一下,没有停。
蒋辉看到他坐在工位上。他知道。
陈稳继续写代码。
十点十五分。茶水间。热水壶的水刚烧开,陈稳把杯子放在台面上等水凉。
蒋辉走进来,手里拿着一个空保温杯。
「你来了。」
「来了。」
蒋辉拧开杯盖,倒水,加凉水,拧上盖子。动作很利落。
「早上我看到告警的时候,」蒋辉说,「我以为你会处理。」
陈稳没有说话。杯子里的热气在冒。
「你处理了。」蒋辉说。不是问句。
「回调地址配成了 IP。」
「我知道。我刚才跟纪衡说的是我处理的。」蒋辉的声音很平,没有解释。
陈稳拿过水壶往自己杯子里倒了八分满,端着往外走。
「陈稳。」蒋辉在身后说。
陈稳没有停。
「我不是故意的。我没想到你会来。」
陈稳端着杯子走回工位。杯子烫,他把杯子放在桌上,没有喝。他想起自己删掉的那两行终端历史。蒋辉如果去查操作记录,只会看到查日志的命令。改配置的几行不见了。蒋辉永远不知道他修了什么。这一刻的信息差是单向的——陈稳知道。蒋辉不知道。
他喝了一口水。还是太烫,舌尖疼了一下。
中午食堂。陈稳打了一份红烧鱼块。吃了几口,手机震了。赵岩的消息:
「门禁审批过了。十二月二十四号之后可以调取。系统管理员日志也在里面。」
陈稳回了「收到」,加了一行:「八月一日那个时间段的门禁,单独标记。」
赵岩回了一个「好」。
十二月二十四日。还有三天。他继续吃鱼。鱼肉是白的,刺已经剔了。吃到一半他想起一件事——十二月二十四日是他爸的生日。他从口袋里掏出手机,找到他爸的号码,打了一段话又删了,重新打:「爸。十二月二十四号我回不来。忙完这一段。」发送。
过了一会儿他爸回了一句:「厂里忙。你忙你的。没事。」
陈稳把手机放回口袋,把剩下的米饭吃完。
下午两点十五分。走廊里遇到张磊,他抱着笔记本快步走过来。
「汇金线的台账你还有吗——十一月份那批。」
陈稳打开抽屉,拿出信封。
张磊翻到第六页,点着「43,200」:「你之前说这个数字是从 43,700 改下来的?」
「对。十一月三日。跟业务线负责人更换同一天。」
张磊从口袋里掏出一张折着的 A4 纸,铺在桌面上。一张打印的对账单,盖着汇金业务线的公章。
「今天上午我去汇金那边要十二月的预估值。他们财务给的预估是四万五千笔。不是四万三千二。」
陈稳看了看那张纸。十二月预估:45,000 笔。打印日期:十二月十八日。纸角折了一下,有一条压痕,像是被人从文件夹里抽出来的时候夹得紧。
他把十一月台账和十二月回执并排放在一起。拉开抽屉,拿出十二月更新的台账——十一月实际结算量 44,180 笔。三张纸在他面前排开,数字在同一条视线上对齐。
43,200(十一月预估值,手写) 44,180(十一月实际值,手写更新) 45,000(十二月预估值,回执)
预估永远比实际低。每次调整都是往下调——11/3 从 43,700 改到 43,200。但实际数据 44,180 比两个预估值都高。真实数据压不住。
「跟别人说过吗。」陈稳问。
「没有。你是第一个。」
「先别跟别人说。」
「包括纪衡?」
「包括纪衡。」
张磊没有问为什么。他把 A4 纸折好放回口袋,转身走了。
陈稳把信封和回执收进抽屉,锁上。他在记事本上写了三个数字,合上本子。
压低预估的目的他不知道。但压低预估会让某件事更容易通过——什么事件需要低的结算量预估值才能通过。他没有答案,不着急。
下午五点零八分。何晚的消息。
「双月会是明天?」
「明天下午。」
「几点回来。」
他不知道。双月会开到几点不知道,开完纪衡会不会找他不知道,门禁记录的事会不会有进展不知道。他不知道的事没法承诺。
「明天晚上。不确定几点。」
何晚的消息隔了半分钟:「你昨天凌晨两点没回来。今天早上七点多回来过一趟吗。」
他没有回去。从办公室出去在便利店门口吃了两个包子,洗了一把脸,又回公司了。
他没有回这条消息。
过了两分钟:「没事。你忙。」
他看着那三个字——没事、你忙。他知道这不是真的。但他不知道怎么回。他打了几个字又删掉,锁了屏。
晚上七点三十九分。陈稳把推广方案 v3.1 改完。六条业务线的数据全部核对了三轮。汇金线数据源写的是「线下台账 + 业务线回执」。他保存文档,合上电脑。
大厅里碰到蒋辉。两个人一前一后出了旋转门。外面冷,风很大。
「陈稳。」
陈稳停下来。
「早上的事,我不该那么说。」蒋辉的声音被风打散了一半,「我进去之前没想到你在。」
陈稳等着他说下去。
「我不会改。说出去的话我不会追回来。但是你——下次你需要什么东西,你跟我说。我补给你。」
蒋辉的表情是认真的,不是客套。他在用自己的方式说谢谢——他能给的方式。他给不了「承认是你修的」,但他能给「下次你需要什么跟我说」。
「不用。」陈稳说。
他转身往地铁站走。风从背后推着,外套被吹得鼓鼓的。
他听到蒋辉在身后说了什么,风盖住了。没有回头。
地铁站入口的黄色灯光在前面。他刷卡进站。
他想起今天早上删掉的那两行终端历史——一个 sed 命令,八行配置,把 IP 改成了服务名。一行命令修好的事,蒋辉用了一个小时排查。他修好之后删了痕迹,让蒋辉以为是自己排查到的。
他不知道这么做对不对。他只知道自己不想让这件事变成公开的账。
地铁来了。门打开。他找了一个靠门的座位坐下。对面坐着一个穿校服的女孩,在写作业。笔尖在纸面上移动,发出沙沙的声音。
他看着那个女孩写了几行字。字很小,一行一行,写得很快。
他闭上眼睛。脑子里在转明天双月会的方案。六条业务线。数据口径。汇金线的三个数字——43,200、44,180、45,000。中间那个是真的。左边和右边都是预估。左边是往下调的预估,右边是另一个口径的预估。
没有答案。但他记住了这三个数字。
地铁广播响了。他睁开眼睛,看到窗玻璃上自己的影子——被隧道里的灯光打散成很多个小块。他认出自己的轮廓,但觉得很陌生。
车停了。有人上车,有人下车。他没有动。
门关上,列车重新启动。他继续看着窗玻璃上那个模糊的影子。明天下午有两件事要做。一件是双月会。另一件自己还没想好,但他知道它在那里。
窗玻璃上的影子在一个隧道口的光里突然清晰了一下,又暗了。
← 第三十八章 凌晨 · 目录 · 第四十章 不是帮你 →