收到线上服务器出现cpu告警一般怎么排查?
当线上服务器出现CPU告警时,可以按照以下步骤进行系统性排查,逐步定位问题根源:
1. 快速确认CPU使用情况
- 命令工具:
top # 实时查看CPU占用(按P排序进程) htop # 增强版top,支持可视化操作 mpstat -P ALL 1 # 查看每个CPU核心的详细利用率 sar -u 1 5 # 历史CPU使用率统计(需安装sysstat)
- 关注指标:
%us
(用户态)高:应用代码消耗CPU。%sy
(内核态)高:系统调用或中断频繁。%wa
(I/O等待):高则可能磁盘/网络IO成为瓶颈。
2. 定位高CPU进程/线程
- 查看进程:
top -c # 显示完整命令,确认可疑进程 ps -eo pid,pcpu,comm,args --sort=-%cpu | head # 按CPU排序进程
- 深入线程:
top -H -p <PID> # 查看指定进程的线程(按P排序) pidstat -t -p <PID> 1 # 统计线程级CPU使用
3. 分析进程内部状态
-
Java应用:
jstack <PID> > thread_dump.log # 生成线程快照 jstat -gcutil <PID> 1000 # 检查GC情况(频繁GC可能导致CPU高)
- 用工具(如fastthread)分析
jstack
输出,查找RUNNABLE
状态的线程及堆栈。
- 用工具(如fastthread)分析
-
其他语言(如C/C++/Go):
pstack <PID> # 查看进程的线程堆栈(可能需gdb) perf top -p <PID> # 实时分析函数级CPU占用 gdb -p <PID> -ex "thread apply all bt" --batch > gdb_dump.log # 生成完整堆栈
4. 检查系统级瓶颈
-
I/O瓶颈:
iostat -x 1 # 查看磁盘IO负载(%util高表示瓶颈) dstat # 综合监控(CPU、磁盘、网络)
-
网络瓶颈:
sar -n DEV 1 # 网络流量统计 ss -s # 查看连接统计(TIME-WAIT过多?)
-
上下文切换/中断:
vmstat 1 # 查看cs(上下文切换)、in(中断) pidstat -w -p <PID> 1 # 进程级上下文切换统计
5. 结合日志与监控
-
应用日志:
- 检查错误日志(如
grep -i error /var/log/app/*.log
)。 - 关注高频日志输出(可能是循环报错或异常逻辑)。
- 检查错误日志(如
-
系统日志:
dmesg | grep -i "error" # 检查内核日志 journalctl --since "5 minutes ago" # 查看近期系统日志(systemd系统)
-
监控系统(如Prometheus、Zabbix):
- 检查历史趋势:CPU升高是否伴随流量突增?
- 关联指标:内存、磁盘、网络、应用中间件(如数据库连接池)。
6. 代码/配置级检查
-
代码热点:
- 使用性能分析工具生成火焰图:
perf record -F 99 -p <PID> -g -- sleep 30 # 采样 perf script > out.perf flamegraph.pl out.perf > flamegraph.svg # 生成火焰图
- 分析火焰图,找到占用CPU高的函数或代码块。
- 使用性能分析工具生成火焰图:
-
配置问题:
- 线程池配置不合理(过多/过少)。
- 缓存失效导致频繁计算。
- JVM参数不当(如堆大小、GC策略)。
7. 安全排查
- 可疑进程:
lsof -p <PID> # 查看进程打开的文件/网络 netstat -antp | grep <PID> # 检查异常连接
- 挖矿病毒:
- 检查未知进程、计划任务(
crontab -l
)、启动项。 - 使用
rkhunter
、chkrootkit
扫描后门。
- 检查未知进程、计划任务(
8. 常见场景速查
-
场景1:GC频繁
现象:jstat
显示GC时间占比高,应用卡顿。
解决:调整JVM堆大小/选择低延迟GC算法(如G1/CMS)。 -
场景2:死循环/死锁
现象:线程堆栈中同一方法反复出现。
解决:分析代码逻辑,修复并发问题。 -
场景3:外部依赖瓶颈
现象:CPU高伴随大量I/O等待或网络超时。
解决:优化数据库查询、增加缓存、降级非核心功能。
总结流程
- 确认问题 → 2. 定位进程 → 3. 分析线程 → 4. 关联日志/监控 → 5. 代码/系统调优
通过工具链逐层下钻,结合系统指标与应用逻辑,最终定位到代码或配置缺陷。