1. 从一次线上事故说起那天凌晨3点我被刺耳的手机警报声惊醒。监控系统显示生产环境某台核心服务器的CPU使用率已经持续超过95%长达15分钟。作为运维负责人我立即通过SSH连入服务器输入top命令后看到几个Java进程几乎吃满了所有CPU资源。这场景让我想起刚入行时前辈的忠告CPU飙高不可怕可怕的是你不知道为什么飙高。2. 快速定位问题进程2.1 基础排查三板斧当CPU使用率异常时这三个命令能快速锁定问题top -c # 动态查看进程资源占用按P按CPU排序 ps -aux --sort-%cpu | head -10 # 静态快照前10高CPU进程 htop # 交互式进程查看器需安装经验在负载极高的服务器上htop可能因资源不足无法启动此时top -c更可靠。添加-c参数可以显示完整命令行这对识别Java/Python等带参数启动的进程特别有用。2.2 解读关键指标在top界面重点关注这些列%CPU进程占用的CPU百分比多核环境下可能超过100%TIME进程累计占用CPU时间突然暴增往往有问题COMMAND进程启动命令注意异常路径或参数我曾遇到一个案例某个java -jar进程占用了800%的CPU查看COMMAND发现是测试环境的JAR包被误部署到生产由于配置错误导致死循环。3. 深入分析线程级状态3.1 查看线程资源占用找到问题进程后假设PID为12345用这些命令深入分析top -H -p 12345 # 查看该进程的所有线程 pidstat -t -p 12345 1 5 # 每1秒采样1次共5次线程级统计3.2 Java进程专项排查对于Java应用jstack是必备工具jstack -l 12345 thread_dump.log # 生成线程快照 jstat -gcutil 12345 1000 5 # 每1秒采集1次GC数据共5次避坑指南在容器环境中直接使用jstack可能报错需要先进入容器命名空间nsenter -t 12345 -m -u -i -n -p jstack -l 14. 性能热点定位实战4.1 火焰图生成与分析安装perf和FlameGraph工具集# Ubuntu/Debian sudo apt install linux-tools-common linux-tools-generic git clone https://github.com/brendangregg/FlameGraph.git # 采集数据采样30秒 perf record -F 99 -p 12345 -g -- sleep 30 perf script | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl flame.svg火焰图中横向宽度代表资源占用比例纵向是调用栈深度。我曾用这个方法发现一个JSON序列化库在循环中频繁创建解析器实例的问题。4.2 系统调用追踪使用strace观察进程行为strace -ff -T -tt -p 12345 -o strace.log关键观察点是否频繁执行open/read等系统调用是否存在大量epoll_wait超时是否有异常的fork操作5. 常见问题模式与解决方案5.1 无限循环类问题特征CPU持续100%无波动线程栈显示固定方法重复调用解决方案通过jstack定位问题代码行检查循环终止条件添加防护性睡眠如Thread.sleep(10)5.2 锁竞争问题特征CPU使用率周期性波动线程状态大量BLOCKED典型案例// 错误示例 public synchronized void process() { // 长时间IO操作 }优化方案减小锁粒度用读写锁替代独占锁避免在锁内执行IO操作5.3 算法效率问题识别方法对比不同输入规模下的CPU耗时使用JMH进行基准测试优化策略时间复杂度从O(n²)优化到O(nlogn)引入缓存机制并行化处理需考虑Amdahl定律6. 长效监控与防御6.1 监控体系搭建推荐配置Prometheus Grafana采集node_exporter的CPU指标ELK收集和分析日志告警规则示例- alert: HighCPUUsage expr: 100 - (avg by(instance)(irate(node_cpu_seconds_total{modeidle}[5m])) * 100) 85 for: 10m6.2 资源限制策略在cgroup层面进行限制# 创建控制组 cgcreate -g cpu:/app_limits # 限制CPU使用为单核的50% echo 50000 /sys/fs/cgroup/cpu/app_limits/cpu.cfs_quota_us echo 100000 /sys/fs/cgroup/cpu/app_limits/cpu.cfs_period_us # 将进程加入控制组 cgclassify -g cpu:/app_limits 123457. 典型案例复盘7.1 日志框架配置错误现象某次发布后CPU持续90% 排查过程top发现多个log进程高负载查看日志配置发现同时开启了Console和File AppenderFile Appender配置了立即刷新immediateFlushtrue解决方案改为异步日志并调整刷新策略7.2 正则表达式灾难问题代码String.matches(^(a|aa)*$) // 对特定输入产生回溯爆炸优化方案预编译正则表达式避免嵌套量词使用更严格的匹配边界8. 进阶工具链推荐8.1 动态诊断工具bpftrace内核级追踪# 统计系统调用次数 bpftrace -e tracepoint:syscalls:sys_enter_* { [probe] count(); }sysdig容器环境诊断sysdig -pc -c topcontainers_cpu8.2 性能分析平台Pyroscope持续profiling工具NetData实时监控仪表盘9. 排查流程总结我总结的通用排查路径全局定位top/htop找问题进程线程分析top -H/pidstat找热点线程堆栈分析jstack/perf定位代码位置行为观察strace/sysdig看系统调用数据验证编写测试用例复现问题最后分享一个实用技巧在/etc/sysctl.conf中添加kernel.panic 10 # 10秒后自动重启 kernel.sysrq 1 # 启用魔术键这样在完全卡死时可以用AltSysRqREISUB安全重启。