引言:CPU告警别慌,先定位再动手

IDC运维中最常见的告警之一就是CPU使用率飙高。很多新手一看到CPU 100%就急着重启机器,结果业务中断、问题复现,根因却没找到。本文从实战出发,梳理一条从topperf的完整排查链路,帮你快速定位是哪个进程、哪类负载吃满了CPU,并给出对应的优化思路。

第一步:用top快速锁定高CPU进程

登录服务器后第一件事就是执行top,按P键按CPU使用率排序,重点关注%CPU列和load average。注意:load average是1/5/15分钟的平均运行队列长度,如果15分钟平均值持续高于CPU核数,说明负载积压已久,不是瞬时抖动。

常见判断:

  • 单个进程CPU接近100%:可能是死循环、加密解密密集型任务或单线程瓶颈
  • 多个进程各占几十%:可能是并发连接暴涨或配置了过大的worker进程数
  • CPU高但top里看不到明显进程:注意%wa(I/O等待)是否偏高,CPU高可能是假象,实际瓶颈在磁盘

第二步:用ps和pidstat细化进程状态

top只能看瞬间值,要观察趋势可以用pidstat:

# 每2秒采样一次,持续10次pidstat -u 2 10# 只看某个进程的线程级CPU占用pidstat -t -p PID 2 10

如果发现进程CPU忽高忽低,配合ps -Lf -p PID查看线程状态,重点看是否有线程长期处于R(运行)状态。Java/Python等带GC的语言,还需要结合GC日志判断是否频繁Full GC导致CPU飙升。

第三步:用vmstat和mpstat区分用户态与内核态

CPU高要分清是用户态(us)还是内核态(sy):

vmstat 1 5mpstat -P ALL 1 5
  • us高:业务代码问题,如死循环、正则回溯、加密操作,或流量突增
  • sy高:系统调用频繁,常见于大量上下文切换、网络小包处理、锁竞争
  • cs(context switch)每秒上万次:多半是线程过多或锁粒度太细
  • st(steal)高:云主机被宿主机超卖,邻居抢占CPU,需联系云厂商

第四步:用perf做火焰图,精准定位热点函数

当进程级定位还不够时,就需要上perf做采样分析。这是定位CPU热点最有效的武器:

# 安装(CentOS/RHEL)yum install -y perf# 对全系统采样30秒perf record -g -a -- sleep 30perf report --stdio# 只采样某个进程perf record -g -p PID -- sleep 30perf report --stdio | head -50

如果环境不允许安装perf,退而求其次可以用strace -cp PID统计系统调用耗时,或者用gdb attach抓取几次线程栈(jstack对应Java进程),人工比对热点。

第五步:结合业务流量与日志判断根因

技术手段定位到进程后,还要回到业务层面确认根因:

  • 查看Web访问日志(Nginx/Apache access log)确认是否有突发流量或爬虫攻击
  • 查看dmesg/var/log/messages确认是否有OOM或内核异常
  • ss -s查看连接数,确认是否连接风暴导致worker进程忙不过来
  • 如果是定时任务时间点(如整点备份、日志切割)触发,多半是任务并发冲突

常见场景与优化方案

场景1:Web服务CPU被打满

优先排查是否被CC攻击或爬虫刷接口。方案:启用WAF限速、调整Nginx的worker_processes为CPU核数、开启keepalive复用连接、必要时上CDN做流量清洗。

场景2:数据库CPU持续高位

SHOW PROCESSLIST和慢查询日志定位SQL,重点看是否有全表扫描、索引失效、排序过大。方案:优化SQL、补充索引、调整innodb_buffer_pool_size,读写分离。

场景3:脚本或程序死循环

perf火焰图会显示某个函数占比极高。方案:修复代码逻辑,同时给脚本加上超时保护(如timeout 300 ./script.sh)和单实例锁(flock),防止重复执行叠加。

场景4:内核态sy高

常见于网卡软中断(softirq)集中在单核。方案:开启RPS/RFS把软中断分散到多核,升级网卡驱动,检查是否有网卡丢包(ethtool -S eth0 | grep drop)。

排查工具速查表

工具用途关键指标
top全局快照%CPU、load average
pidstat进程/线程趋势%CPU随时间变化
vmstat系统整体us/sy/cs/st
mpstat多核分布各核负载是否均衡
perf热点函数采样火焰图
strace系统调用调用耗时分布

结语

CPU排查的核心思路是:先看全局(top/vmstat)→ 锁定进程(pidstat)→ 深入内核/热点(perf)→ 回归业务(日志/流量)→ 对症优化。记住一个原则:重启只能救急,不能治病。把根因记录到运维知识库,下次同类告警就能直接对号入座,把平均故障定位时间从小时级缩短到分钟级。