摘要:"叮——" 2025年3月18日凌晨2:47,我的企业微信突然弹出SRE团队的通告:【生产告警】订单服务/create接口P99响应时间突破8秒,触发熔断机制,当前故障等级:P0。
"叮——" 2025年3月18日凌晨2:47,我的企业微信突然弹出SRE团队的通告:【生产告警】订单服务/create接口P99响应时间突破8秒,触发熔断机制,当前故障等级:P0。
登录阿里云ARMS控制台,实时监控曲线显示TPS从1200骤降到43,错误率突破90%。我习惯性先看数据库指标——等等,MySQL CPU使用率才18%?这不符合常规认知啊!(后来证明这里犯了第一个误判,过度依赖经验主义)
"这破接口上周压测明明扛住了5000QPS,难道DBA偷偷改了连接池配置?" 快速执行show variables like '%max_connections%',结果显示数值正常。此刻研发群里已炸锅:"前端用户投诉支付成功但订单丢失!"
排查步骤
使用Arthas的trace命令追踪SQL执行路径[arthas@20263]$ trace com.xxx.order.dao.OrderMapper createOrder "#cost > 500"结果显示MyBatis执行耗时仅23ms,但有个可疑现象:JDBC Connection获取耗时占整体80%
检查连接池配置原配置:spring.datasource.hikari.maximum-pool-size=50 spring.datasource.hikari.minimum-idle=20通过vmtool动态获取连接池对象:
[arthas@20263]$ vmtool --action getInstances --class com.zaxxer.hikari.HikariDataSource发现active连接数始终维持在48-50区间,但wait队列堆积超过2000。等等,这不符合Hikari的默认等待策略啊!复查代码发现某同事擅自添加了:
dataSource.setLoginTimeout(60); //错误配置导致等待队列失控修正连接池配置后,TPS回升到800但1分钟后再次雪崩。此时运维传来关键线索: "GC时间从日常的200ms/5min暴涨到8s/30s!"
JDK版本差异带来的排查陷阱:
JDK8的CMS日志:[ParNew: 34944K->34944K(39296K), 0.0000233 secs]JDK17的ZGC日志:[GC(3) Garbage Collection (Warmup) 4096M->1024M, 0.002ms] 新老GC日志格式差异导致初期误判停顿时间(教训:跨版本排查需重置知识体系)使用jstack抓取线程快照,发现大量BLOCKED线程:
"http-nio-8080-exec-2" #20 daemon prio=5 os_prio=0 tid=0x00007f48740e9800 nid=0x6f21 waiting for monitor entry [0x00007f482b7e7000] java.lang.Thread.State: BLOCKED (on object monitor) at com.xxx.coupon.service.CouponLock.tryLock(CouponLock.java:112) - waiting to lock (a java.util.concurrent.ConcurrentHashMap)Arthas诊断实录:
[arthas@20263]$ thread -n 3 #查看最忙线程[arthas@20263]$ monitor -c 10 com.xxx.coupon.service.CouponLock tryLock #统计调用频次[arthas@20263]$ watch com.xxx.coupon.service.CouponLock tryLock params #观察入参特征最终锁定是优惠券服务的双重校验锁引发死锁,这个"锁王"竟然在分布式锁内部又加了本地锁!
在修复死锁后,接口响应时间仍存在300ms左右的毛刺。通过JFR(JDK Flight Recorder)抓取到的事件:
追溯代码发现某算法工程师写的特征处理代码:
// 优化前(魔鬼代码)Double features = new Double[1024*1024]; //每次请求分配1M Double数组(这段代码在JDK8的ParNew GC下表现正常,但在JDK17的ZGC中,由于NUMA架构敏感特性,导致内存分配速率突破阈值)
最后的解决方案颇具戏剧性:将Double改为double,内存占用从8MB降到1MB,ZGC停顿时间立即回归正常范围。这个案例让我想起2019年处理过的一个类似故障——历史总是惊人地相似,只是换了件马甲。
本次排查暴露的典型问题链:
当我们在凌晨四点最终解决问题时,团队新人问了个有趣的问题:"为什么不用AI自动修复?"我的回答是:"故障排查就像法医验尸,AI能检测伤口位置,但串联证据链仍需人类逻辑。"这或许就是工程师存在的终极价值——在混沌中建立秩序,在绝望中寻找微光。
来源:电脑技术汇