服务器CPU使用率过高,核心解决思路是“先定位再处理”:通过监控工具找出是哪个进程或负载导致的,然后针对性地优化代码、扩容资源或调整系统配置,而不是盲目重启或加服务器。
为什么你的服务器CPU会突然飙高
CPU使用率过高不是无缘无故的,常见原因就那么几类,你可以对照排查。
- 应用程序Bug或死循环:代码里出现死循环、无限递归,或者某个逻辑在特定数据下陷入长时间计算。
- 流量突增:促销活动、热点事件、被爬虫集中抓取,导致并发请求超过系统设计容量。
- 数据库查询慢:一条没走索引的SQL语句,可能把CPU耗在大量扫描行上。
- 恶意攻击:CC攻击、DDoS攻击的流量会占用大量CPU资源处理无效请求。
- 系统本身问题:比如Linux内核的软中断(softirq)处理异常,或某个内核线程异常占用CPU。
业内专家指出,多数CPU打满的情况并不是服务器性能不够,而是某个具体环节出了问题,先诊断,再花钱升级,能省下不少成本。
第一步:快速定位CPU占用高的进程
拿到一台CPU飙升的服务器,别急着重启,先登录上去,用系统自带的工具看是谁在吃CPU。
用top命令两分钟锁定进程
执行top,然后按大写字母P,进程会按CPU使用率从高到低排序,重点看这些字段:
%CPU:进程占用CPU的百分比,超过100%表示用了多核。PID:进程ID,后续排查要用。COMMAND:进程名,能大致判断是Web服务、数据库还是其他程序。
如果有一个进程CPU占用接近100%甚至更高,记录下它的PID,然后执行top -p PID单独观察这个进程,确认它是否持续占用而非瞬时波动。
用ps命令看完整路径
top显示的进程名可能被截断,用下面命令看完整信息:
ps aux | grep PID
或者直接按CPU排序:
ps aux --sort=-%cpu | head -20
这样可以看清启动命令、运行用户、CPU累积时间,如果发现是java、php-fpm、python等常见服务进程,进入下一步。
查线程级别的消耗
如果一个进程占用大量CPU,但你不确定是哪个线程,用top -H -p PID查看该进程下的所有线程,找出线程ID,然后结合
jstack(Java)、gdb(C/C++)等工具做线程转储,定位到具体代码行,这一步对Java应用尤其常见,很值得学习。
第二步:分析CPU被消耗的具体场景
定位到进程后,需要判断是正常业务负载还是异常行为。
正常流量导致的高CPU
如果进程是Nginx或Tomcat,CPU高往往和请求量有关,看top里的load average,对比服务器核数:负载长期高于核数,说明排队严重,可以查访问日志统计请求量:
tail -1000 /var/log/nginx/access.log | awk '{print $4}' | sort | uniq -c | sort -rn | head
如果发现某个IP访问量异常大,可能是爬虫或攻击,用iptables或防火墙规则临时封禁。
数据库慢查询导致CPU高
MySQL或Redis实例CPU高,先查慢查询日志。
SHOW GLOBAL STATUS LIKE 'Slow_queries';
如果慢查询数量持续增长,打开慢日志分析具体SQL,常见优化手段包括给查询条件加索引、避免SELECT 、控制单次查询数据量,对于Redis,需要检查是否有超大key或频繁执行KEYS命令,这类命令会阻塞CPU。
应用代码逻辑问题
如果进程是业务程序,CPU高对应的时间点是否有新版本发布、定时任务触发、缓存失效?建议看日志找关联,比如定时任务在整点扫描全表,或者缓存雪崩导致大量请求打到数据库,都会造成CPU飚升,这种情况下,就算加服务器也治标不治本,必须改代码。
第三步:采取降载与扩容措施
定位到原因后,根据紧急程度选择处理方式。
临时降载:快速抑制CPU持续走高
- 限制进程CPU使用:用
cpulimit工具限制进程占用的CPU百分比,例如cpulimit -p PID -l 80让该进程最高使用80% CPU,这样能保住系统其他服务的基本响应。 - 重启服务:如果是死循环或异常状态,重启服务能立刻释放CPU,但注意先保存必要日志,重启后要验证问题是否会复现。
- 切换流量:如果服务器前面有负载均衡,把部分流量切到其他节点,给当前机器腾出处理时间。
扩容:对稳定增长的业务做规划
如果高CPU是业务自然增长导致的,比如用户量持续上升,临时降载只是缓兵之计,这时候考虑:
- 纵向扩容:提高单机CPU核数或更换更高主频的处理器,适合单机应用,操作简单但受限于单台机器的硬件上限。
- 横向扩容:增加服务器数量,用负载均衡分担请求,适合无状态应用,但需要处理会话共享和缓存一致性问题。
- 弹性伸缩:在云平台上配置自动扩容规则,比如CPU使用率持续超过75%时自动增加云服务器实例,据工信部公开信息,国内公有云市场近年来增长迅速,弹性伸缩已经成为主流标配功能。
优化代码和查询:长期解决办法
临时措施治标,优化才能治本。
- 代码层面:排查循环逻辑,加缓存(Redis或本地缓存),减少重复计算;异步化非核心流程,避免阻塞请求线程。
- 数据库层面:用
EXPLAIN分析慢SQL,补齐索引;拆分大事务;读写分离,把查询压力分开。 - 架构层面:引入消息队列削峰填谷,把突发流量变成可控的处理速率,这样即使某个时段请求量飙升,CPU也不会被打满。
如何设置CPU使用率监控告警
CPU问题不能全靠人工发现,建议给服务器配置监控和告警,在CPU使用率过高之前就收到通知。
用系统自带工具做基础监控
- 安装
sysstat,使用sar -u 1 5查看CPU实时和历史统计。 - 配置
crontab定时记录mpstat和pidstat的数据,保留一周以上的历史,便于事后分析。
用云平台监控或开源监控系统
- 云平台自带监控(如简米云云监控、酷番云监控)支持配置CPU使用率阈值,超过80%发送短信、邮件或钉钉通知。
- 开源方案推荐Prometheus + Grafana,先在被监控机器上安装
node_exporter,然后配置采集规则和告警规则,例如当rate(node_cpu_seconds_total{mode="idle"}[5m])持续低于20%时触发告警。
告警阈值该怎么定
不建议把阈值设成100%再告警,那样太晚了,多数业务系统CPU长期高于80%就会明显影响响应速度,建议按严重程度分两级:
| 级别 | 阈值 | 响应动作 |
|---|---|---|
| 预警 | CPU使用率超过70%持续10分钟 | 登录查看进程,确认是否有异常 |
| 严重 | CPU使用率超过90%持续5分钟 | 立即介入,考虑降载或扩容 |
阈值不是死的,如果服务器核数多、业务并发高,可以适当上调;如果是核心数据库,建议下调,关键在于持续观察基线,根据日常负载情况调整告警灵敏度。
Linux CPU排查常用命令清单
如果你对命令行不太熟悉,下面这些命令建议收藏,每条都附了使用场景。
top:查看系统负载、进程CPU排行。vmstat 1:每秒输出一次系统全局状况,观察CPU空闲和等待I/O的比例。mpstat -P ALL 1:查看每核CPU使用率,判断是否存在单核被打满而其他核空闲的情况。pidstat -p PID 1:持续观察指定进程的CPU使用率。strace -p PID:追踪进程的系统调用,能发现进程卡在哪个操作上。perf top:性能分析工具,直接显示消耗CPU最多的内核和用户态函数。uptime:快速查看1分钟、5分钟、15分钟负载趋势,判断负载是在上升还是下降。
顺带提一个容易忽略的点:CPU使用率高但系统负载不高,这种情况往往是某个进程在忙等(比如自旋锁),但并没有产生太多可运行队列,反过来,CPU使用率不高但负载很高,可能是进程在等待I/O,处理思路完全不同,别只看一个指标。
服务器CPU使用率过高常见问答
为什么服务器CPU使用率偶尔会突然跳到99%然后又降下来?
这种情况大多和定时任务、日志压缩、数据备份等周期性操作有关,比如每天凌晨的日志切割会影响几分钟,属于正常现象,但如果频繁出现,就去crontab -l查看脚本,检查是否有任务执行时间重叠,或者某个脚本写得不合理导致资源竞争。
扩容服务器CPU核数之后CPU使用率为什么没降下来?
单看CPU使用率是百分比数字,核数增加后,分子(实际CPU占用时间)如果不变,分母变大,使用率应该降下来,但很多扩容场景下,业务代码是单线程或无状态依赖,增加核数并不能让进程利用多核能力,这时候需要排查进程是否只跑在一个核上,用mpstat -P ALL确认,并检查代码是否存在单线程阻塞整个应用的瓶颈。
云服务器CPU使用率高和独立服务器CPU使用率高处理方式有区别吗?
没有本质区别,排查思路完全一致,云服务器额外的好处是可以快速扩容和创建快照,操作上更灵活,但代价是如果CPU持续高,云服务商可能会限制实例性能,甚至触发系统维护,所以云服务器上更建议配置弹性伸缩和负载均衡,让单台机器压力自动分散,无论哪种服务器,先定位进程、再优化业务,才是正确的顺序。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/708625.html





