服务器负载高怎么排查原因

文章导读
服务器负载高时,先不要急着加 CPU 或重启服务。load average 反映的是处于可运行和不可中断状态的任务数量,它高不等于 CPU 忙:可能是进程在等磁盘 I/O、等网络文件系统,也可能是瞬时突发。排查顺序建议固定为:先看 load 与 CPU 核数的比例和趋势,再看是 CPU 密集、I/O 等待还是内存换页,最后才落到具体进程和配置。改动前记录当前值,单次改动只动一个变量,否则后面无法判
📋 目录
  1. 壹 服务器负载高先定位在哪一层
  2. 贰 服务器负载高:先看这四个位置
  3. 叁 服务器负载高:按可能性从高到低排除
  4. 肆 服务器负载高:改完怎么确认真的解决了
A A

服务器负载高时,先不要急着加 CPU 或重启服务。load average 反映的是处于可运行和不可中断状态的任务数量,它高不等于 CPU 忙:可能是进程在等磁盘 I/O、等网络文件系统,也可能是瞬时突发。排查顺序建议固定为:先看 load 与 CPU 核数的比例和趋势,再看是 CPU 密集、I/O 等待还是内存换页,最后才落到具体进程和配置。改动前记录当前值,单次改动只动一个变量,否则后面无法判断哪个动作起了作用。

判断服务器负载高,先算 load average 与逻辑核数的比值:1 分钟值持续高于核数就值得查,高于核数两倍以上通常已有明显排队。用 uptime、top、vmstat 1 区分 CPU 忙、I/O 等待、内存换页三类原因,再定位到进程。不要用加 swap、清缓存、重启服务当性能优化,它们只争取时间。改动后至少观察 30 分钟、跨越一个业务高峰再判断是否稳定,并提前准备回滚命令。

服务器负载高先定位在哪一层

负载是结果,不是原因。按下面四层自上而下判断,可以避免在错误的层反复改配置。

  • 业务层:请求量是否突增、是否有慢查询、是否刚发版。检查位置是应用日志和上游接入层访问日志,判断依据是错误率和响应时间是否同步上升。
  • 进程层:哪个进程吃 CPU 或处于 D 状态。检查位置是 top 按 P、M 排序,以及 ps -eo stat,pid,comm,pcpu,pmem --sort=-pcpu | head -20。判断依据是单个进程长期占满一个核,或多个进程同时排队。
  • 系统资源层:CPU、内存、磁盘、网络的哪一项先到瓶颈。检查位置是 vmstat 1 5,看 r(运行队列)、wa(I/O 等待)、si/so(换页)。判断依据是 r 持续大于核数说明 CPU 排队,wa 偏高且 si/so 非零说明磁盘或内存拖累。
  • 宿主机/虚拟化层:如果是云主机或容器,检查位置是控制台的 CPU 积分、CPU steal、磁盘 IOPS 限额。判断依据是 top 里 st(steal)明显,说明资源被同宿主其他实例占用,本机优化作用有限。

多数情况到进程层就能定位。如果四层都正常但 load 仍然高,需要怀疑不可中断 I/O,例如挂载的网络存储失联,这类进程在 top 中表现为 D 状态且难以 kill。

服务器负载高:先看这四个位置

下面四个位置按顺序看,每个都给出可直接执行的命令或路径。

服务器负载高怎么排查原因

1. 系统整体指标

uptime
nproc
vmstat 1 10
mpstat -P ALL 1 5   # 需 sysstat,未安装可先看 /proc/stat
iostat -xz 1 5      # 需 sysstat
free -m

重点看 uptime 的三个 load 值是否递增、vmstat 的 r 和 wa 列、iostat -x 的 %util 与 await。三个 load 值里 1 分钟高、15 分钟低,多为瞬时突发;反过来则说明问题已持续。

2. 进程与线程现场

ps -eo pid,ppid,stat,pcpu,pmem,etime,comm --sort=-pcpu | head -20
ps -eo stat,pid,comm | awk '$1 ~ /^D/ {print}'   # 找不可中断进程
top -H -p <PID>   # 看该进程内哪个线程最忙

D 状态进程需要用 cat /proc/<PID>/stack 或 cat /proc/<PID>/wchan 进一步确认它在等什么。

3. 应用日志与系统日志

journalctl -p err --since "-30 min" --no-pager
tail -n 200 /var/log/syslog        # Debian/Ubuntu
tail -n 200 /var/log/messages      # CentOS/RHEL
dmesg -T | tail -n 100             # 看内核报错、OOM、磁盘错误

应用日志路径以实际部署为准,常见为 /var/log/nginx/error.log、/var/log/mysql/error.log,或容器内 docker logs --tail 200 <容器名>。看到 OOM killer 记录说明内存已到边界,此时 load 高是结果不是原因。

服务器负载高怎么排查原因

4. 配置项与面板字段

Nginx 的 worker_processes、worker_connections 在 /etc/nginx/nginx.conf;MySQL 的 max_connections、innodb_buffer_pool_size 用 SHOW VARIABLES LIKE 'max_connections'; 查当前值;PHP-FPM 的 pm.max_children 在 /etc/php/*/fpm/pool.d/www.conf。云控制台的监控面板要看 CPU 使用率、CPU 积分余额、磁盘 IOPS/吞吐上限,具体字段名和限速额度各厂商不同,以控制台实际展示和对应计费文档为准。

服务器负载高:按可能性从高到低排除

  1. 流量或请求突增。确认动作:对比接入层日志的单位时间请求数,例如 awk '{print $4}' access.log | cut -c14-17 | sort | uniq -c | tail -20,看是否集中在某几分钟。处理:限流、扩容或临时摘流量,先止血再分析。
  2. 慢查询或数据库连接堆积。确认动作:MySQL 执行 SHOW PROCESSLIST; 看是否有大量 Sleep 或长时间 Query,配合 SHOW ENGINE INNODB STATUS\G。处理:终止异常连接、补索引,调整连接池上限。
  3. 磁盘 I/O 瓶颈。确认动作:iostat -xz 1 5 中某块盘 %util 接近饱和且 await 明显偏高。处理:减少大文件写入、日志轮转、把高 I/O 任务错峰;换盘属于资源变更,需要评估。
  4. 内存不足触发换页。确认动作:vmstat 1 的 si/so 持续非零,free -m 的 available 很低。处理:定位占用内存的进程(ps --sort=-pmem),调整应用内存上限;加 swap 只能延缓,不建议当解决办法。
  5. 单进程死循环或阻塞。确认动作:某进程 CPU 长期顶满且线程栈无变化,用 cat /proc/<PID>/wchan 或 gdb -p <PID> -batch -ex 'thread apply all bt' 看卡在哪里(生产环境执行 gdb 有停顿风险,需谨慎)。处理:按应用自身机制重启或摘除该实例。
  6. 定时任务叠加。确认动作:crontab -l、ls /etc/cron.d/,对照 load 升高的时间点。处理:错开执行时间或降低并发。

以上顺序不是绝对,容器环境要更早看 cgroup 限额:cat /sys/fs/cgroup/cpu.max(cgroup v2)或 cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us(v1),路径随发行版和容器运行时不同,需要以本机实际存在的文件为准。

服务器负载高:改完怎么确认真的解决了

改动后先用与排查时相同的命令复测,保持口径一致:

服务器负载高怎么排查原因
uptime
vmstat 1 30
ps -eo stat,pid,pcpu,comm --sort=-pcpu | head -10

判断标准建议为:15 分钟 load 回落到逻辑核数以下并保持平稳,vmstat 的 r 列不再持续大于核数,wa 和 si/so 恢复正常。观察时长至少覆盖一个业务高峰周期,没有明显峰谷规律的服务建议观察 1 小时以上再看是否复发。如果是云主机,同时到控制台监控页确认 CPU 使用率曲线与实例内一致,避免只看了实例内数据而漏掉宿主机层面的限流。

回滚办法要在动手前准备好。改配置文件的,先备份:

cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak.$(date +%F-%H%M)
nginx -t && systemctl reload nginx
# 回滚
cp /etc/nginx/nginx.conf.bak.<时间戳> /etc/nginx/nginx.conf && nginx -t && systemctl reload nginx

调整过连接数、线程数等运行时参数的,记录原值并准备对应恢复命令;重启过服务的,确认重启前后版本和配置一致,避免把“重启后恢复”误判为“配置改对了”。如果改动涉及扩缩容,回滚同样要走控制台或编排工具,不要只改实例内配置。