线上服务CPU飙高接口超时应急处置实战:从load爆表到快速定位根因,一次线上救火全记录

兄弟们,做后端和运维的,线上服务CPU持续飙高、load average爆表、接口响应从毫秒级退化到超时,这类告警大家肯定都处理过。

这类事故的核心矛盾就一个:CPU飙高只是表象,背后可能是业务流量暴涨、代码死循环、频繁Full GC、慢SQL拖垮连接池、锁竞争,甚至是被植入了挖矿木马。 必须快速定位到底是哪一种,不能盲目重启掩盖问题。

在动手之前,先把这四条"保命纪律"刻在脑子里,事故后严禁执行以下操作

  1. 不要上来就重启服务! 现场信息全丢,重启完根因找不到,问题还会再犯。
  2. 不要看CPU高就杀掉疑似可疑的进程! 你以为是挖矿木马,结果把核心业务进程杀了。
  3. 不要在没抓top和日志证据前就盲目扩容或重启! 掩盖问题等于埋雷。
  4. 不要只看CPU不看load和IO! CPU不高但load爆表,大概率是IO等待或者锁竞争,排查方向完全不一样。

下面直接上干货,完整复盘我们的标准处置SOP。


一、 标准处置流程:先留证据,后止血

记住八字真言:先留证据,再动手

完整流程:告警确认 → 现场留证(快照) → 快速止血(判断摘流量还是观察) → 定位根因(进程→线程→代码) → 恢复业务 → 监控回归 → 复盘防再犯。

二、 Linux系统级排查:揪出嫌疑进程

上了机器,先别慌,按顺序敲命令,把系统级快照留下来。

bash 复制代码
# 1. 看load趋势和运行时间
uptime

# 2. top命令看全局,进去后按大写 P 键,按CPU占用排序
top
# 找到最耗CPU的进程PID,比如是 12345

# 3. 如果top卡死,用ps直接抓快照
ps aux --sort=-%cpu | head -n 20

# 4. 看多核CPU分布,确认是所有核都高,还是单核被打满(单核高大概率是死循环)
mpstat -P ALL 1 5

# 5. 看CPU、IO和上下文切换(us高是用户态,sy高是内核态,wa高是IO等待)
vmstat 1 10

# 6. 判断是不是IO等待导致load高
iostat -dx 1 5

# 7. 看历史CPU使用率,确认是突然飙高还是慢慢爬升
sar -u 1 5

⚠️ 顺便排查是否被挖矿:

bash 复制代码
# 查异常外联IP
ss -antp | grep ESTABLISHED
# 查陌生定时任务
crontab -l
# 查最近修改的可疑文件
find /tmp /var/tmp -type f -mmin -60

三、 Java应用级排查:定位到代码行

如果确认是Java进程(比如PID 12345)在疯狂吃CPU,继续往下挖。

bash 复制代码
# 1. 找出这个进程里最耗CPU的线程ID (TID)
top -Hp 12345

# 2. 把线程ID转成十六进制(假设线程ID是 12500)
printf "%x\n" 12500
# 输出: 30d4

# 3. 抓线程栈快照(多抓几次,间隔2秒,方便对比)
jstack 12345 > jstack_1.log
sleep 2
jstack 12345 > jstack_2.log

# 4. 在jstack日志里搜刚才的十六进制线程ID (0x30d4)
grep -A 30 "nid=0x30d4" jstack_1.log

在栈里找线索:

  • 看到 RUNNABLE 且一直在业务代码里循环:大概率是死循环
  • 看到 BLOCKEDWAITING 在等锁:大概率是锁竞争
  • 看到大量 GC task thread:大概率是频繁Full GC

辅助诊断命令:

bash 复制代码
# 看GC次数和耗时(每秒刷一次,看FGC次数和耗时是不是在狂飙)
jstat -gcutil 12345 1000

# 看堆内对象统计(按实例数排序,看是不是某个对象泄漏了)
jmap -histo 12345 | head -n 20
# 【⚠️生产高危】千万别在生产随便用 jmap -dump:format=b,file=heap.hprof,全量dump极易引发二次Full GC直接把服务搞挂!

# 如果装了Arthas,直接用神器
# 查看最忙的前3个线程
thread -n 3
# 生成CPU火焰图,一眼看出哪行代码在烧CPU
profiler start
profiler stop --format html

Java常见根因总结:

  1. Full GC频繁:老年代满,内存泄漏或大对象突增。
  2. 死循环:代码逻辑Bug,或者正则表达式回溯(单核CPU打满)。
  3. 锁竞争:synchronized或ReentrantLock粒度太大,线程全在排队。
  4. 慢SQL拖垮连接池:数据库慢查询导致线程全阻塞在获取连接上。
  5. 线程池耗尽:下游服务超时,当前服务线程池队列打满,疯狂创建线程或拒绝。

四、 中间件场景排查差异

有时候CPU高的不是业务应用,而是中间件。

1. MySQL CPU飙高

  • 成因:慢SQL(没走索引、全表扫描)、复杂JOIN、并发太高。
  • 排查 :登进MySQL执行 show processlist; 看State和Time。去查慢查询日志(slow log),拿到SQL后用 explain 看执行计划。

2. Redis CPU飙高

  • 成因 :大Key操作(如 hgetall 一个几MB的Hash)、热Key集中访问、缓存穿透/击穿/雪崩、复杂命令(如 keys *)。
  • 排查redis-cli --hotkeys 找热Key,redis-cli --bigkeys 找大Key,slowlog get 10 看慢日志。用 info clients 看连接数是不是打满了。

3. Nginx CPU飙高

  • 成因:并发连接数过高、keepalive配置不当、后端响应太慢导致Nginx worker阻塞、遭遇CC攻击。
  • 排查 :看 access.log 的QPS和IP分布。用 strace -p <worker_pid> -c 看系统调用耗时。检查 worker_connectionskeepalive_timeout 参数。

五、 快速止血与恢复(保命操作)

定位需要时间,但业务不能一直挂着,必须快速止血。

哪些情况必须立即摘流量或重启?

  • 服务已经OOM边缘,或者发生死锁完全无响应。
  • 确认是下游依赖彻底挂了,当前服务跟着拖死。
  • 注意:重启前,务必把刚才的jstack、jstat、heap histo、慢SQL日志打包发给自己或传到OSS!

哪些情况必须先抓现场再动?

  • CPU高但服务还能勉强响应,接口没大面积超时。
  • 还没抓到jstack和线程快照。

摘流量的落地方法:

  1. 网关/负载均衡踢节点 :在Nginx、APISIX或微服务网关层,把故障节点的权重调为0,或者直接从注册中心下线,千万别直接拔网线或kill进程
  2. Kill慢查询 :如果是MySQL慢SQL导致,写个脚本循环 killshow processlist 里Time超过阈值的连接。
  3. 接口限流:在网关层对非核心接口开启限流,保住核心交易链路。

六、 验证与上线(别急着下班)

根因修复、代码发版后,别以为就万事大吉了。

  1. 确认指标回落 :盯着监控,看CPU使用率降到正常水位,load average 回到核数以内。
  2. 接口延迟回归:看APM(如SkyWalking/Pinpoint)或网关监控,接口P99延迟回到基线水平。
  3. 灰度放量观察:先放10%流量,没问题再50%、100%。
  4. 持续盯盘:发版后至少盯盘半小时,重点看GC频率和load,确认没有复发再收工下班。

七、 事后预防(填坑闭环)

救火只是治标,复盘防再犯才是治本。

  1. 监控告警阈值:CPU > 80% 持续3分钟告警,接口P99 > 500ms告警,FGC > 1次/分钟告警。
  2. 压测与容量规划:大促前必须做全链路压测,摸清系统水位,提前扩容。
  3. 慢SQL治理:上线前必须过SQL审核,严禁无索引查询,定期跑慢SQL巡检报告。
  4. 线程池/连接池参数:根据压测结果合理设置核心线程数、最大线程数和队列大小,拒绝默认配置打天下。
  5. JVM参数调优:合理设置新生代/老年代比例,选择合适的垃圾回收器(如G1/ZGC),避免频繁Full GC。
  6. 限流降级熔断:核心接口必须配Sentinel或Resilience4j,下游挂了要能优雅降级,不能跟着一起死。

八、 总结:处置高频踩坑血泪教训

最后,总结几个兄弟们最容易踩的坑,希望大家别再交学费:

  1. 上来就重启丢现场:重启一时爽,排查火葬场。重启前不保留jstack和heap,根因永远是个谜。
  2. 把业务进程当挖矿进程误杀 :看到个不认识的进程名直接 kill -9,结果把核心网关杀了。杀进程前一定要 ls -l /proc/<pid>/exe 看清楚。
  3. 只看CPU不看IO和GC:CPU 10%但load 50,你去查代码有个屁用?那是磁盘IO瓶颈或者锁等待。
  4. 慢SQL没抓到就下结论:数据库一慢,就拍脑袋说是网络问题。没看执行计划和慢日志前,别乱甩锅。
  5. 靠加机器掩盖问题没找根因:CPU高了就加机器,结果代码里的死循环或者内存泄漏没解决,机器加到100台照样被打挂,成本还翻倍。

线上排查拼的就是肌肉记忆和标准动作。希望这篇实战复盘能帮大家在遇到CPU飙高时少走弯路,精准定位。

如果你觉得这篇文章对你有帮助,或者在排查时有什么独门秘籍,欢迎点赞、收藏、转发!在评论区聊聊你遇到过最坑的CPU飙高原因,我们一起交流避坑!

相关推荐
大大大大晴天️16 分钟前
大数据上 K8s 的三种运行范式:离线计算、实时流处理与分析服务
大数据·kubernetes
2601_9620725021 分钟前
大数据-234 离线数仓 - 异构数据源 DataX 将数据 从 HDFS 到 MySQL
大数据·mysql·hdfs
fb_123451 小时前
虚拟化技术介绍
运维·服务器
treacle田1 小时前
达梦数据库-Linux DM主备集群动态增加节点-记录总结
linux·运维·数据库·达梦主备集群动态扩展
FIT2CLOUD飞致云1 小时前
1Panel AI一体机(GB10版)推出MiniMax H3本地视频生成方案
运维·ai·开源·1panel·ai视频·运维面板
ARM|X86+FPGA工业主板厂家1 小时前
基于Jetson TX2的矿用巡检机器人
linux·运维·机器人
一只专注api接口开发的技术猿1 小时前
Open Claw 实战|快速搭建电商商品监控与数据分析能力
大数据·数据库·数据挖掘·数据分析
杨云龙UP1 小时前
Oracle 19c RMAN历史备份清理失败:CONTROL_FILE_RECORD_KEEP_TIME 问题排查与整改实战
linux·运维·网络·数据库·oracle·rac
Fxkj8881 小时前
企业新媒体IP陪跑真实价值解析:合作体验与效果评判标准
大数据·人工智能·tcp/ip·媒体