5分钟定位,10分钟解决。
这话一点不夸张,上周半夜我真在生产环境里亲自干了这单活。报警弹出来的时候,场景很直白:监控说核心服务CPU蹭到了95%,我远程连上去,看了一圈,发现是算折扣的一个方法一直在打转。改了个配置,服务马上回稳。过程不复杂,但细节不少,我就把整个排查的来龙去脉倒着讲给你听——像放一段故障回放,从结果往前倒带。
当时我是这么干的:报警→连上目标机→跑几条Arthas命令→定位到具体代码行→临时改配置→问题消停。讲命令带来的效果比较直观。thread命令把占CPU多的线程找出来,看到12586这个线程占了92.5% CPU,几乎把机器压住。把这个线程的堆栈抓出来一看,马上能看出问题躺在
OrderService.calculateDiscount 里,条件判断有问题,走进了死循环。把逻辑修正或者临时加一层保护条件,CPU立刻回落。整个从接警到确认是死循环,再到临时修复,不到十分钟就结束了。
再往细里说。用watch在生产上挂方法监控,想看入参和返回值的变化。用户反馈订单金额算错,我就把算折扣的方法用watch盯着。几分钟后,输出告知我:VIP用户的100元订单被打成了5折。明显不对——按理说只有特定促销才会打折。继续追,发现配置中心里某个键值被误改,导致代码走错分支。另外,watch还把一次空指针异常直接暴露出来:当userId为12345时,执行到第67行抛了NPE。拿到行号之后,加个空值检查或保护就能防止崩溃。
性能问题上,我用trace把调用链路掏透。拿一个下单慢的例子trace,发现 processOrder 总耗时是8.7毫秒,但其中 checkStock 花了5.2毫秒,占了将近一半时间。顺着这条线去看代码和外部调用,发现库存校验是走外部接口的同步查询,内网延迟把时间吃掉。把那步改成异步预热或加本地缓存后,响应时间明显回升。trace的好处就是把注意力收窄到真正慢的那一段,免得在代码里到处乱翻。
把常见问题并起来说:CPU飙高、方法抛异常、接口变慢,这三种线上问题最常见。以前碰这种事,常常是翻日志、抓thread dump、重启观察,费时还影响业务。目前用Arthas,许多时候不必重启就能连上JVM,直接看线程堆栈、方法入参、调用耗时。举个对比:像刚才的CPU问题,老办法可能得一到两个小时才能定位,这次用Arthas5到10分钟就搞定;方法抛异常,以前常常要半小时以上才能找到触发条件,目前开watch两分钟就能把异常位置和触发条件看清楚;性能瓶颈的定位,过去有时摸不到点在哪儿,目前trace三分钟之内就能把主要慢点挖出来。你觉得夸张不夸张自己评判,但效率的确 上了一个档次。
再把时间线往前拉一点,讲报警和准备工作。那晚是统一监控平台发的CPU阈值告警,告警里指明某台机器上服务进程CPU持续高位。我先登录运维台验证,确认不是监控误报:CPU曲线是真的高。接下来不能乱动,先抓process的top、jstack快照和堆占用情况,但我更倾向马上用Arthas attach到进程,由于可以实时交互,省得重启停服务。登录到目标主机,attach到对应PID,用thread找占CPU的线程。
操作上有些细节值得注意。attach时检查JVM版本和权限,生产环境一般用root或部署用户,确认权限够再操作。拿到线程列表后,记下高占比线程ID,用thread -n或thread -b抓堆栈。如果看到死循环或自旋,别急着kill,把堆栈和调用链先落盘,方便回溯。怀疑跟配置有关时,马上去配置中心比对最近改动记录,许多问题就是热更时把值写错了。
补几次典型例子来丰富场景。遇到线程互等锁时,堆栈会有明显等待信息。一次生产故障里,thread-1和thread-2相互等对方释放同一把锁,分别在不同资源上等对方,典型死锁。把两条堆栈对照后能定位到锁持有点,短期解决可能是调整锁粒度或降级处理,长远是改代码逻辑。还有内存问题,线上频繁出现Full GC,heap占用一直上升。Arthas的trace和thread看不出对象分配来源,我用heapdump导出内存做本地分析,发现某个缓存没有设置过期,数据一直往里丢,造成泄漏。给缓存加过期策略或定期清理后,Full GC 问题消失。
工具的价值不只是那些命令能跑出来的数据,关键在它能让你在活着的进程上做实时诊断。别把它当灵丹妙药,输出还得结合业务逻辑和配置变更记录来判断。现场的一个常用套路是:确认报警是真实的→快速定位占资源的线程或方法→把堆栈、方法入参、调用耗时抓全→核对配置、代码提交记录和外部依赖状态→临时缓解(列如改配置或隔离某依赖)→再回归改码或上线热修。把这套流程练熟,比单纯会几个命令更重大。
说点实操细节,省你现场瞎摸索的时间。watch时别盯着高频繁调用的方法全量输出,会把控制台刷爆。我常在watch里带条件表达式,只看包含特定userId或订单号的调用,这样既能复现问题又不影响整体性能。trace时设定合理的limit深度,别把整条调用链都铺开。抓堆栈和dump时,把文件同步到分析主机,别让生产机的IO被占死。操作之前把当前的pid、JVM参数和机器指标记录一下,方便事后复盘。
再补一点权限和风险方面的提醒。attach这种事在一些公司有严格审批流程,操作前最好把值班或负责人叫上,避免误操作;在权限受限的环境,先和运维或安全团队沟通好。做临时改配置来止血时,要留回滚点,别直接在线上改了就不管。还有,任何对业务有影响的操作都尽量在非高峰时间做,或先在预生产环境演练一遍。
按我十年摸的经验,把工具和流程结合起来,才是真正在生产里能稳定用的办法。工具会更新,故障形式也会变,但能把“好像慢”“感觉怪”这种模糊问题,变成“具体代码行/具体配置项/具体外部依赖”的定位流程,才是核心。练这套东西不容易,要在非高峰环境多演练,把常用命令和排查步骤形成自己的checklist,遇到半夜报警也不会手忙脚乱。
现场问题常常比日志截图看上去复杂,熟练工具能少踩坑。要是你手上有典型案例,发出来我可以挑几例写成详细复盘,大家一起看看怎么下手。







![[C++探索之旅] 第一部分第十一课:小练习,猜单词 - 鹿快](https://img.lukuai.com/blogimg/20251015/da217e2245754101b3d2ef80869e9de2.jpg)










暂无评论内容