新闻详情

新闻详情

首页 / 资讯中心 / 详情

关于我如何用一个bug让自己加班到凌晨三点这件事

发布时间:2026/8/30 23:12:29来源:尧图网络
关于我如何用一个bug让自己加班到凌晨三点这件事
这事儿得从昨天下午说起。周五下午四点半我已经在收拾东西准备跑路了。测试那边丢过来一个issue说生产环境有个接口偶尔超时让我看一眼。偶尔超时这种词儿在程序员字典里基本等于大概率是你的问题但我懒得查日志。我打开skywalking看了下调用链没毛病啊响应时间平均120ms挺正常的。又翻了翻nginx日志也没有明显慢请求。我就回了一句这边看正常再观察一下。然后测试就炸了。他贴了张截图请求时间15:47:23响应时间3.2秒。我一看这个时间点心里咯噔一下——那个时间我刚发完一个版本重启了服务。你以为的bug其实是feature接下来就是一个小时的血泪排查。先怀疑是缓存失效导致回源DB查了redis命中率99.8%正常。再怀疑是日志打印太多把IO堵了看了下logback的异步队列积压为0正常。怀疑是GC问题看了眼GC日志频率正常单次耗时也都在50ms以内。然后我注意到一个细节这个超时请求里带了一个特殊的headerx-request-id的格式是abc-123-def这种但正常我们内部生成的格式是UUID.randomUUID().toString()全是横杠分段的那种。我就顺着这个header往上查发现这个请求经过了一个网关服务而网关里有个拦截器会对这个header做一次MD5计算然后塞到MDC里用于链路追踪。MD5计算本身不慢但这个拦截器的实现是这样的String requestId request.getHeader(x-request-id); if (StringUtils.isNotBlank(requestId)) { // 为了兼容旧版本对非标准格式的requestId做一次摘要 if (!requestId.matches(^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$)) { requestId DigestUtils.md5DigestAsHex(requestId.getBytes()); } }这个正则每次请求进来都要执行一次。大部分请求的requestId都是标准UUID匹配很快。但那个特殊请求的requestId是不带横杠的短格式正则引擎在做回溯匹配的时候复杂度直接起飞了。再加上那个时间点服务刚重启JIT还没热身解释执行模式下这个正则匹配的耗时从纳秒级飙升到了秒级。问题找到了改法很简单把正则匹配改成尝试按UUID格式解析抛异常就说明不是标准格式再做MD5。try { UUID.fromString(requestId); } catch (IllegalArgumentException e) { requestId DigestUtils.md5DigestAsHex(requestId.getBytes()); }三行代码改完测试环境验证通过预发布验证通过准备发生产。有时候顺风顺水反而让人害怕发生产的流程走了半个多小时——code review、merge、构建镜像、滚动更新。整个过程异常顺利顺到我心里有点发毛。果然上线后五分钟监控突然弹出一堆告警错误率飙到15%全是NullPointerException。我当时整个人是懵的。改的就是一个拦截器里的小逻辑怎么干出NPE了赶紧回滚。回滚后服务恢复然后我开始看错误日志。堆栈指向的代码行是String traceId MDC.get(traceId); Span span tracer.buildSpan(traceId).start();traceId是null所以buildSpan的时候抛了NPE。那traceId为什么是null呢因为设置traceId的逻辑就在我改的那个拦截器里在requestId的基础上又加了一层处理。我改完之后对于非标准格式的requestId走MD5分支这个没问题。但问题是我改代码的时候把一个前置的判断条件顺手优化掉了。原来的代码是if (StringUtils.isNotBlank(requestId)) { // 设置traceId MDC.put(traceId, generateTraceId(requestId)); }我重构的时候觉得isNotBlank这个判断跟后面正则匹配的逻辑有重叠就给合并了变成了javaif (requestId ! null requestId.matches(...)) { // 只对标准格式处理 }这样非标准格式的requestId就直接跳过了整个逻辑连MDC都没设置。更隐蔽的是之前那个拦截器的逻辑里即使requestId是空也会用UUID.randomUUID()生成一个兜底的traceId。我重构的时候把这个兜底逻辑挪到了一个我认为更合适的位置但那个位置在某些异常路径下根本执行不到。所以结果就是部分请求的traceId没设置下游服务拿不到traceId就崩了。凌晨两点的感悟问题最终在凌晨两点修复了。改回去三行加了三行注释发版观察了二十分钟一切正常。回家路上我在想一个问题我为什么会在周五下午去动一个看起来可以优化但已经在线上跑了两年的代码答案其实挺简单的——我看到那段正则匹配的时候就难受职业病犯了。总觉得这种写法不优雅性能有隐患应该重构一下。但事实上那个接口的QPS也就200多那个正则匹配即使是最差情况对整个系统的影响也微乎其微。我花了一个小时定位了一个非关键问题然后用一个不那么稳妥的方案修复了它最后引入了一个更严重的bug。你说这事儿怪谁怪测试没覆盖全怪CR没看出来说到底还是怪我自己没守住线上代码能不动就不动这条底线尤其是周五下午四点半这个死亡时间点。写这段文字的时候已经是周六了。我给自己立了个规矩以后周五下午三点之后除了紧急故障任何代码变更都不做。优化代码这种事儿留给周三上午脑子最清醒的时候干。别学我。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

蔡氏电路实战指南:从仿真到硬件实现双涡卷混沌 2026/8/31 0:07:47

蔡氏电路实战指南:从仿真到硬件实现双涡卷混沌

Chuas Circuit听起来像是某个电子学教材里的练习题,但它其实是混沌理论里面最经典、也最适合亲手折腾的一个实验对象。只要一个非线性电阻、两个电容、一个电感和一个可调电阻,就能在示波器上看到那种像蝴蝶翅膀一样的双涡卷吸引子。对于想真正理解“确定…

阅读更多 →
Howland电流源精讲:从原理到调试的全流程工程指南 2026/8/31 0:07:47

Howland电流源精讲:从原理到调试的全流程工程指南

1. 这个电路到底解决什么问题 1.1 为什么需要压控电流源 说来也怪,很多刚接触模拟电路的人,想到信号传输第一反应全是“电压输出”。电压信号确实直观,一量就知道,但实际工程里电压信号在长线传输、传感器激励、电化学测量这些场…

阅读更多 →
STM32N657 SWO引脚矛盾:CubeMX显示PB3,数据手册为PB5 2026/8/31 0:07:47

STM32N657 SWO引脚矛盾:CubeMX显示PB3,数据手册为PB5

拿到STM32N657这颗料的第一天,我就撞上了一个让人原地懵圈的引脚矛盾:CubeMX里清清楚楚显示SWO在PB3,翻开数据手册的引脚说明表,却赫然写着PB5。对于一个靠SWO输出调试日志吃饭的人而言,这种"工具和手册打架"…

阅读更多 →
STM32C5设备支持包(IAR DFP)安装指南与常见坑 2026/8/31 0:07:47

STM32C5设备支持包(IAR DFP)安装指南与常见坑

上一阵子在IAR里折腾一块基于STM32C5系列的新板子,工程从STM32CubeMX导出来之后怎么都编译不过。报错信息很干脆:找不到设备描述文件。跟着错误路径去查,发现指向的是一个让我愣了一下的名字:STMicroelectronics.stm32c5xx.2.1.0.…

阅读更多 →
【机组组合】基于Benders分解算法解决混合整数规划问题——机组组合问题附Matlab代码 2026/8/31 0:07:47

【机组组合】基于Benders分解算法解决混合整数规划问题——机组组合问题附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…

阅读更多 →
STM32WB用Custom Template从零定制私有BLE GATT服务 2026/8/31 0:02:35

STM32WB用Custom Template从零定制私有BLE GATT服务

做BLE产品开发这几年,被问得最多的问题之一就是:"标准服务跑通了,但我要做的是客户自己的私有协议,怎么搞?"如果你用的是STM32WB,答案就在ST的LAT1197应用笔记里——用Custom Template从零定制一…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞