一、问题背景
生产环境中最常遇到的运维场景之一就是服务器负载突然飙升,导致业务响应变慢甚至不可用。监控告警平台频繁报警 Load Average 过高,SSH 登录服务器都变得卡顿。这时候如何快速定位根因、采取有效措施恢复业务,考验的是运维工程师对 Linux 系统资源模型的理解深度和实战经验积累。
很多时候我们会发现,Load Average 高不一定等于 CPU 使用率高,也不一定是内存不足导致。真实原因可能是磁盘 IO 瓶颈、网络流量暴增、僵尸进程堆积、软中断过高、内核任务卡死等多种可能。因此排查负载问题必须建立完整的观察链路和判断逻辑,避免盲目重启服务或者凭感觉调整参数。
本文从实战角度出发,系统梳理 Linux 负载的核心概念、排查路径、工具使用、命令解读、常见根因和修复手段,力求形成完整的排查闭环。
二、适用场景
本文内容适用于以下典型场景:
- 监控告警显示服务器 Load Average 持续高于正常水平
- 用户反馈业务响应缓慢或超时
- SSH 登录服务器明显卡顿
- 应用日志出现大量慢请求或队列堆积
- 数据库查询变慢、连接数暴增
- 容器节点资源使用率异常
- 定时任务或批处理作业导致系统资源紧张
- 系统升级、扩容、迁移后性能下降
无论是物理机、虚拟机还是云主机,只要运行的是 Linux 内核,本文的排查思路和命令都适用。
三、核心知识点
3.1 什么是 Load Average
Load Average 是 Linux 系统用来衡量系统繁忙程度的指标,表示在特定时间段内处于可运行状态(R 状态)和不可中断睡眠状态(D 状态)的平均进程数。
通常我们看到的是三个数值,分别代表过去 1 分钟、5 分钟、15 分钟的平均负载。
bashuptime
# 输出示例:
# 14:23:45 up 10 days, 3:15, 2 users, load average: 2.35, 1.80, 1.50
这里的 2.35, 1.80, 1.50 就是 Load Average。
R 状态进程
处于 Running 或 Runnable 状态的进程,它们正在使用 CPU 或等待 CPU 调度。
D 状态进程
处于不可中断睡眠状态(Uninterruptible Sleep)的进程,通常在等待 IO 操作完成,例如磁盘读写、NFS 挂载卡死等。
这类进程无法被信号中断,也无法被 kill 掉,只能等 IO 完成或者重启系统。
3.2 Load Average 多高算高
这个问题没有绝对标准,需要结合 CPU 核心数判断。
一般规则:
- Load Average 接近或小于 CPU 核心数:系统正常
- Load Average 是 CPU 核心数的 1.5 倍以上:需要关注
- Load Average 是 CPU 核心数的 2 倍以上:已经严重拥堵
例如一台 4 核服务器:
- Load Average 在 3 以下:正常
- Load Average 在 4-6 之间:需要排查
- Load Average 超过 8:严重拥堵
但这只是经验值,还需要结合业务特点和历史基线判断。
3.3 Load Average 高的可能原因
- CPU 密集型任务过多
- 磁盘 IO 瓶颈
- 网络 IO 高
- 内存不足触发 swap
- 软中断过高
- 僵尸进程堆积
- 内核任务卡死
- NFS、CIFS 等远程文件系统挂载异常
- 驱动或硬件故障
3.4 排查原则
- 先整体后局部:先看系统整体指标,再看具体进程
- 先观察后操作:收集足够信息再做决策
- 先排除明显问题:优先排查 CPU、内存、磁盘、网络四大资源
- 先非侵入后侵入:优先使用查看类命令,避免一上来就重启服务
- 记录现场:保存关键命令输出,便于事后复盘
四、整体排查思路
排查 Load Average 过高问题,推荐按以下流程进行:
步骤 1:确认负载确实异常
步骤 2:检查 CPU 使用情况
步骤 3:检查内存使用情况
步骤 4:检查磁盘 IO 情况
步骤 5:检查网络流量
步骤 6:检查进程状态分布
步骤 7:定位具体进程
步骤 8:分析进程行为
步骤 9:采取修复措施
步骤 10:验证效果
步骤 11:复盘总结
五、实战步骤
步骤 1:确认负载确实异常
目的
避免误判,先确认 Load Average 确实超出正常范围。
命令
bashuptime
预期输出
14:30:12 up 10 days, 3:21, 2 users, load average: 8.56, 7.23, 6.10
异常表现
- 1 分钟负载远高于 5 分钟和 15 分钟负载:突发性问题
- 三个负载值都很高且持续上升:持续性问题
- 负载值超过 CPU 核心数的 2 倍以上
判断逻辑
先确认 CPU 核心数:
bashgrep -c processor /proc/cpuinfo
# 或者
nproc
假设输出是 4,说明是 4 核服务器。
如果 Load Average 是 8.56,说明平均有 8.56 个进程在等待 CPU 或 IO,已经是核心数的 2 倍以上,属于严重拥堵。
下一步动作
继续排查 CPU 使用情况。
步骤 2:检查 CPU 使用情况
目的
确认 Load Average 高是否由 CPU 使用率高导致。
命令
bashtop
重点观察第三行 %Cpu(s) 部分:
%Cpu(s): 85.2 us, 10.5 sy, 0.0 ni, 2.3 id, 1.5 wa, 0.0 hi, 0.5 si, 0.0 st
各字段含义:
us:用户空间 CPU 占用sy:内核空间 CPU 占用ni:nice 优先级调整后的用户态 CPU 占用id:空闲 CPUwa:等待 IO 的 CPU 占用hi:硬中断占用si:软中断占用st:虚拟机被宿主机偷走的 CPU 时间
异常表现
us或sy很高(超过 80%):CPU 密集型任务过多wa很高(超过 30%):磁盘 IO 瓶颈si很高(超过 20%):网络流量大或网卡中断处理不过来id很低(低于 10%):CPU 已经接近饱和
判断逻辑
如果 id 接近 0,说明 CPU 确实被占满,需要进一步定位是哪些进程在消耗 CPU。
如果 wa 很高,说明很多进程在等待 IO,需要排查磁盘。
如果 si 很高,说明网络中断处理占用了大量 CPU,需要排查网络流量或网卡配置。
下一步动作
如果 CPU 使用率高,跳到步骤 7 定位具体进程。
如果 wa 高,继续步骤 4 检查磁盘 IO。
如果 CPU 使用率不高但 Load Average 高,可能是内存或 IO 问题,继续步骤 3。
步骤 3:检查内存使用情况
目的
确认是否因为内存不足导致频繁 swap,从而拖慢系统。
命令
bashfree -h
预期输出
total used free shared buff/cache available
Mem: 7.6G 5.2G 200M 100M 2.2G 2.1G
Swap: 2.0G 1.8G 200M
异常表现
- Swap 使用率超过 50%
available内存小于 500Mused接近total
判断逻辑
如果 Swap 使用量很大且 available 内存很少,说明内存不足。
进一步确认是否有频繁 swap in/out:
bashvmstat 1 5
关注 si 和 so 列:
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
3 2 1843200 204800 102400 2252800 5120 3840 1024 2048 8000 12000 65 20 10 5 0
si:每秒从 swap 读入内存的数据量(KB)so:每秒从内存写入 swap 的数据量(KB)
如果 si 和 so 持续不为 0 且数值较大,说明系统在频繁 swap,这会严重拖慢系统。
下一步动作
如果确认是内存不足,需要:
- 定位占用内存最多的进程
- 考虑扩容内存
- 优化应用内存使用
- 调整 swap 策略
继续步骤 7 定位具体进程。
步骤 4:检查磁盘 IO 情况
目的
确认是否因为磁盘 IO 瓶颈导致大量进程处于 D 状态。
命令
bashiostat -x 1 5
预期输出
Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await aqu-sz rareq-sz wareq-sz svctm %util
sda 50.2 120.5 2048.3 4096.7 5.2 10.5 9.38 8.02 15.3 25.6 3.25 40.8 34.0 8.5 95.2
重点关注:
%util:磁盘繁忙程度,接近 100% 说明磁盘已经饱和await:平均每次 IO 请求的等待时间(毫秒),超过 20ms 需要关注r_await:读请求平均等待时间w_await:写请求平均等待时间aqu-sz:平均队列长度,大于 1 说明有排队
异常表现
%util接近或等于 100%await超过 50msaqu-sz大于 5
判断逻辑
如果 %util 接近 100% 且 await 很高,说明磁盘已经成为瓶颈。
需要进一步确认是哪些进程在进行大量 IO 操作。
bashiotop -o
-o 参数表示只显示正在进行 IO 的进程。
预期输出
Total DISK READ: 50.2 M/s | Total DISK WRITE: 80.5 M/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
1234 be/4 mysql 30.5 M/s 50.2 M/s 0.00 % 85.23 % mysqld
5678 be/4 root 15.3 M/s 20.1 M/s 0.00 % 45.67 % rsync
可以看到 mysqld 和 rsync 在进行大量磁盘 IO。
下一步动作
如果确认是磁盘 IO 瓶颈,需要:
- 定位具体进程和 IO 操作类型
- 检查是否有大文件操作、备份任务、日志写入等
- 考虑优化应用 IO 模式
- 考虑升级磁盘或使用 SSD
- 检查文件系统是否有异常
继续步骤 7 定位具体进程。
步骤 5:检查网络流量
目的
确认是否因为网络流量过大导致软中断过高,从而占用大量 CPU。
命令
bashsar -n DEV 1 5
预期输出
14:35:01 IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s
14:35:02 lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00
14:35:02 eth0 15234.50 18567.20 45678.30 67890.50 0.00 0.00 0.00
关注:
rxpck/s:每秒接收的数据包数txpck/s:每秒发送的数据包数rxkB/s:每秒接收的数据量(KB)txkB/s:每秒发送的数据量(KB)
异常表现
- 网络收发包数超过 10 万/秒
- 网络流量接近带宽上限
- 网络流量突然暴增
判断逻辑
如果网络流量很大,可能导致网卡软中断过高。
进一步确认软中断情况:
bashcat /proc/softirqs
关注 NET_RX 和 NET_TX 行,这两行代表网络接收和发送的软中断次数。
如果数值持续快速增长,说明网络软中断很高。
还可以用 top 查看 CPU 的 si 占比:
bashtop
# 观察 %Cpu(s) 行的 si 值
如果 si 超过 20%,说明软中断占用了较多 CPU。
下一步动作
如果确认是网络流量导致的问题,需要:
- 定位哪些进程在进行大量网络 IO
- 检查是否有攻击流量
- 检查是否有异常连接
- 考虑优化应用网络模式
- 考虑启用网卡多队列、RPS、RFS 等优化
继续步骤 7 定位具体进程。
步骤 6:检查进程状态分布
目的
统计各种状态的进程数量,重点关注 R 状态和 D 状态进程。
命令
bashps -eo stat | sort | uniq -c | sort -rn
预期输出
45 S
12 R
8 D
5 I
2 Z
1 STAT
各状态含义:
R:运行或等待运行S:可中断睡眠D:不可中断睡眠(等待 IO)Z:僵尸进程T:停止或被追踪I:空闲内核线程
异常表现
R状态进程数量远超 CPU 核心数D状态进程数量较多(超过 5 个)Z状态进程数量较多(超过 10 个)
判断逻辑
如果 D 状态进程很多,说明很多进程在等待 IO,这会导致 Load Average 升高但 CPU 使用率不一定高。
如果 R 状态进程很多,说明 CPU 调度繁忙,需要定位是哪些进程在争抢 CPU。
如果 Z 状态进程很多,说明有大量僵尸进程,虽然不会占用资源,但可能是应用逻辑有问题。
下一步动作
继续步骤 7 定位具体进程。
步骤 7:定位具体进程
目的
找出占用资源最多或状态异常的进程。
方法 1:使用 top 查看 CPU 占用
bashtop
# 按 P 键按 CPU 使用率排序
# 按 M 键按内存使用率排序
记录 CPU 占用最高的前几个进程的 PID 和命令。
方法 2:使用 ps 查看所有进程
bashps aux --sort=-%cpu | head -20
按 CPU 使用率倒序排列,显示前 20 个进程。
bashps aux --sort=-%mem | head -20
按内存使用率倒序排列。
方法 3:查看 D 状态进程
bashps aux | awk '$8 ~ /D/ {print $0}'
列出所有处于 D 状态的进程。
方法 4:查看僵尸进程
bashps aux | awk '$8 ~ /Z/ {print $0}'
列出所有僵尸进程。
预期输出
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
mysql 1234 85.2 15.3 2048000 1024000 ? R 10:30 120:45 /usr/sbin/mysqld
www 5678 25.6 8.5 1024000 524288 ? R 12:15 45:20 /usr/bin/php-fpm
异常表现
- 某个进程 CPU 占用长期超过 80%
- 某个进程内存占用超过 50%
- 有多个进程处于 D 状态
- 有大量僵尸进程
判断逻辑
记录异常进程的 PID、用户、命令、资源占用情况,继续分析进程行为。
下一步动作
继续步骤 8 分析进程行为。
步骤 8:分析进程行为
目的
深入分析异常进程的具体行为,确认根因。
方法 1:查看进程打开的文件
bashlsof -p <PID>
可以看到进程打开了哪些文件、socket、设备等。
重点关注:
- 是否打开了大量文件
- 是否有文件句柄泄漏
- 是否访问了远程文件系统
- 是否有网络连接异常
方法 2:查看进程的系统调用
bashstrace -p <PID> -c -f
-c 表示统计系统调用次数和耗时,-f 表示跟踪子进程。
Ctrl+C 停止后会输出统计结果:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
65.23 2.345678 123456 19 read
20.45 0.734567 12345 60 write
8.12 0.291234 5678 51 poll
3.20 0.115012 2345 49 futex
2.00 0.071890 1234 58 epoll_wait
可以看出进程主要在做什么操作。
如果 read 或 write 占比很高且耗时长,说明在进行大量 IO 操作。
如果 futex 或 epoll_wait 占比高,说明进程在等待锁或事件。
方法 3:查看进程的堆栈
bashpstack <PID>
输出进程的函数调用堆栈,可以看到进程卡在哪个函数调用上。
方法 4:查看进程的 IO 统计
bashcat /proc/<PID>/io
输出示例:
rchar: 123456789
wchar: 987654321
syscr: 12345
syscw: 54321
read_bytes: 102400000
write_bytes: 204800000
cancelled_write_bytes: 0
rchar:进程读取的字符数wchar:进程写入的字符数read_bytes:进程实际从磁盘读取的字节数write_bytes:进程实际写入磁盘的字节数
如果 read_bytes 和 write_bytes 很大,说明进程在进行大量磁盘 IO。
方法 5:查看进程的网络连接
bashlsof -i -a -p <PID>
列出进程的所有网络连接。
或者:
bashnetstat -antp | grep <PID>
或者:
bashss -antp | grep <PID>
方法 6:查看进程的线程
bashps -eLf | grep <PID>
或者:
bashtop -H -p <PID>
-H 参数表示显示线程。
可以看到进程有多少线程,每个线程的 CPU 和内存占用。
判断逻辑
根据上述信息综合判断:
- 如果进程在进行大量磁盘 IO,可能是日志写入、数据库查询、文件操作等
- 如果进程在进行大量网络 IO,可能是网络请求、数据传输等
- 如果进程 CPU 占用高但系统调用不多,可能是计算密集型任务
- 如果进程有大量网络连接,可能是连接池耗尽、连接泄漏等
- 如果进程打开了大量文件,可能是文件句柄泄漏
下一步动作
根据分析结果,采取相应的修复措施。
步骤 9:采取修复措施
场景 1:某个进程 CPU 占用过高
临时措施
降低进程优先级:
bashrenice +10 -p <PID>
这会降低进程的调度优先级,让其他进程有更多机会获得 CPU。
根本措施
- 优化应用代码逻辑
- 检查是否有死循环、频繁计算等问题
- 考虑限流、降级、熔断等保护机制
- 考虑扩容或负载均衡
风险提醒
renice 只是临时缓解,不能解决根本问题。
如果直接 kill 进程,需要确认业务影响和重启方案。
场景 2:内存不足导致频繁 swap
临时措施
清理缓存:
bashsync
echo 3 > /proc/sys/vm/drop_caches
sync 确保脏页写入磁盘,echo 3 清理 page cache、dentries 和 inodes。
风险提醒
清理缓存会导致后续文件 IO 变慢,因为需要重新读取文件到内存。
生产环境慎用,仅在内存极度紧张且确认缓存占用过多时使用。
根本措施
- 定位占用内存最多的进程
- 优化应用内存使用
- 考虑扩容内存
- 调整 swappiness 参数:
bashcat /proc/sys/vm/swappiness
# 默认值通常是 60
# 临时调整
echo 10 > /proc/sys/vm/swappiness
# 永久调整
echo "vm.swappiness = 10" >> /etc/sysctl.conf
sysctl -p
swappiness 值越小,系统越倾向于使用物理内存而不是 swap。
但设置过低可能导致内存不足时系统变得更慢。
场景 3:磁盘 IO 瓶颈
临时措施
暂停或限速正在进行的大文件操作、备份任务、日志归档等。
如果是某个进程导致的,可以用 ionice 降低其 IO 优先级:
bashionice -c3 -p <PID>
-c3 表示 Idle 调度类,只有在没有其他 IO 请求时才会执行。
根本措施
- 优化应用 IO 模式,减少随机读写
- 使用 SSD 代替机械硬盘
- 增加磁盘缓存
- 检查文件系统是否有碎片
- 检查是否有慢查询导致数据库 IO 过高
- 检查日志轮转配置,避免单个日志文件过大
场景 4:网络流量过大导致软中断高
临时措施
限制网络流量或暂停非关键服务。
根本措施
- 启用网卡多队列:
bashethtool -l eth0
# 查看网卡队列数
ethtool -L eth0 combined 4
# 设置为 4 个队列
- 启用 RPS(Receive Packet Steering):
bashecho f > /sys/class/net/eth0/queues/rx-0/rps_cpus
- 启用 RFS(Receive Flow Steering):
bashecho 32768 > /proc/sys/net/core/rps_sock_flow_entries
echo 2048 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt
- 优化应用网络模型,减少短连接
- 考虑使用负载均衡分散流量
场景 5:D 状态进程堆积
原因分析
进程处于 D 状态通常是在等待 IO 操作完成,常见原因:
- 磁盘故障或慢盘
- NFS 挂载超时或卡死
- iSCSI 存储异常
- 驱动或内核 bug
排查方法
查看 D 状态进程的堆栈:
bashcat /proc/<PID>/stack
输出示例:
[<0>] wait_on_page_bit_common+0x123/0x456
[<0>] __filemap_get_folio+0x234/0x567
[<0>] ext4_write_begin+0x345/0x678
[<0>] generic_perform_write+0x456/0x789
[<0>] ext4_buffered_write_iter+0x567/0x890
[<0>] ext4_file_write_iter+0x678/0x901
[<0>] new_sync_write+0x789/0x012
[<0>] vfs_write+0x890/0x123
[<0>] ksys_write+0x901/0x234
[<0>] __x64_sys_write+0x012/0x345
[<0>] do_syscall_64+0x123/0x456
[<0>] entry_SYSCALL_64_after_hwframe+0x234/0x567
可以看到进程卡在文件写入操作上。
临时措施
如果是 NFS 挂载问题,尝试强制卸载:
bashumount -f /mnt/nfs
# 或者
umount -l /mnt/nfs
-f 表示强制卸载,-l 表示延迟卸载。
风险提醒
强制卸载可能导致数据丢失,慎用。
如果 D 状态进程无法清理,可能只能重启系统。
根本措施
- 检查磁盘健康状态:
bashsmartctl -a /dev/sda
- 检查 NFS 配置和网络连接
- 检查存储设备是否正常
- 考虑更换故障硬件
场景 6:僵尸进程堆积
原因分析
僵尸进程是子进程已经退出,但父进程没有调用 wait() 或 waitpid() 回收子进程资源。
僵尸进程不会占用 CPU 和内存,但会占用进程号,数量过多可能导致无法创建新进程。
排查方法
找到僵尸进程的父进程:
bashps -ef | grep defunct
或者:
bashps -eo pid,ppid,stat,comm | awk '$3 ~ /Z/ {print $0}'
记录父进程的 PID(PPID 列)。
修复措施
给父进程发送 SIGCHLD 信号,提示其回收子进程:
bashkill -s SIGCHLD <父进程PID>
如果父进程本身有 bug 无法回收,只能重启父进程:
bashkill <父进程PID>
# 或者强制杀掉
kill -9 <父进程PID>
风险提醒
重启父进程前需要确认业务影响。
根本措施
修复应用代码,确保正确处理子进程退出。
步骤 10:验证效果
目的
确认修复措施是否有效,负载是否恢复正常。
命令
再次检查 Load Average:
bashuptime
再次检查 CPU、内存、磁盘、网络:
bashtop
free -h
iostat -x 1 5
sar -n DEV 1 5
预期结果
- Load Average 下降到正常范围
- CPU idle 比例上升
- 磁盘
%util下降 - 内存 swap 使用率下降
- D 状态进程数量减少
异常表现
如果负载仍然很高,说明问题没有解决或者还有其他根因,需要继续排查。
下一步动作
如果问题解决,继续步骤 11 复盘总结。
如果问题未解决,回到步骤 2 重新排查。
步骤 11:复盘总结
目的
记录排查过程、根因、修复措施、验证结果,便于后续参考和改进。
复盘要点
- 问题触发时间和表现
- 监控告警内容
- 排查路径和关键命令
- 定位的根因
- 采取的修复措施
- 验证结果
- 是否需要优化监控告警
- 是否需要优化应用架构
- 是否需要扩容或升级硬件
复盘输出
形成故障报告或知识库文档,包含:
- 问题描述
- 影响范围
- 根因分析
- 修复措施
- 预防措施
- 经验教训
六、常用命令
以下是排查 Load Average 过高时常用的命令,按场景分类。
6.1 查看负载和运行时间
bashuptime
6.2 查看 CPU 信息
bash# 查看 CPU 核心数
grep -c processor /proc/cpuinfo
nproc
# 查看 CPU 详细信息
lscpu
# 查看 CPU 使用情况
top
htop
# 查看 CPU 历史数据
sar -u 1 5
6.3 查看内存信息
bash# 查看内存使用情况
free -h
# 查看内存详细统计
cat /proc/meminfo
# 查看 swap 使用情况
swapon -s
# 查看内存交换统计
vmstat 1 5
6.4 查看磁盘 IO 信息
bash# 查看磁盘 IO 统计
iostat -x 1 5
# 查看各进程磁盘 IO
iotop -o
# 查看磁盘使用情况
df -h
# 查看 inode 使用情况
df -i
# 查看磁盘健康状态
smartctl -a /dev/sda
6.5 查看网络信息
bash# 查看网络流量
sar -n DEV 1 5
ifstat
nload
# 查看网络连接
netstat -antp
ss -antp
# 查看网卡队列
ethtool -l eth0
# 查看软中断统计
cat /proc/softirqs
6.6 查看进程信息
bash# 查看所有进程
ps aux
ps -ef
# 按 CPU 使用率排序
ps aux --sort=-%cpu | head -20
# 按内存使用率排序
ps aux --sort=-%mem | head -20
# 查看进程状态分布
ps -eo stat | sort | uniq -c | sort -rn
# 查看 D 状态进程
ps aux | awk '$8 ~ /D/ {print $0}'
# 查看僵尸进程
ps aux | awk '$8 ~ /Z/ {print $0}'
# 查看进程树
pstree -p
# 查看进程详细信息
top -p <PID>
htop -p <PID>
6.7 分析进程行为
bash# 查看进程打开的文件
lsof -p <PID>
# 查看进程的网络连接
lsof -i -a -p <PID>
# 查看进程的系统调用
strace -p <PID> -c -f
# 查看进程的堆栈
pstack <PID>
cat /proc/<PID>/stack
# 查看进程的 IO 统计
cat /proc/<PID>/io
# 查看进程的线程
ps -eLf | grep <PID>
top -H -p <PID>
# 查看进程的状态
cat /proc/<PID>/status
# 查看进程的命令行
cat /proc/<PID>/cmdline
# 查看进程的环境变量
cat /proc/<PID>/environ
6.8 调整进程优先级
bash# 降低进程 CPU 优先级
renice +10 -p <PID>
# 降低进程 IO 优先级
ionice -c3 -p <PID>
6.9 内存管理
bash# 清理缓存(慎用)
sync
echo 3 > /proc/sys/vm/drop_caches
# 查看和调整 swappiness
cat /proc/sys/vm/swappiness
echo 10 > /proc/sys/vm/swappiness
# 查看内存大页
cat /proc/meminfo | grep -i huge
6.10 系统信息
bash# 查看内核版本
uname -r
# 查看系统版本
cat /etc/os-release
# 查看系统日志
journalctl -xe
dmesg | tail -50
# 查看负载历史
sar -q 1 5
七、配置示例
7.1 优化 swap 使用策略
编辑 /etc/sysctl.conf:
ini# 降低 swap 使用倾向
vm.swappiness = 10
# 增加脏页刷新频率
vm.dirty_background_ratio = 5
vm.dirty_ratio = 10
使配置生效:
bashsysctl -p
7.2 启用网卡多队列
查看网卡支持的队列数:
bashethtool -l eth0
输出示例:
Channel parameters for eth0:
Pre-set maximums:
RX: 4
TX: 4
Other: 0
Combined: 4
Current hardware settings:
RX: 1
TX: 1
Other: 0
Combined: 1
设置为最大队列数:
bashethtool -L eth0 combined 4
7.3 启用 RPS 和 RFS
RPS 配置(以 4 核服务器为例):
bash# 设置 RPS CPU 掩码(0xf 表示使用 CPU 0-3)
echo f > /sys/class/net/eth0/queues/rx-0/rps_cpus
RFS 配置:
bash# 设置全局流表大小
echo 32768 > /proc/sys/net/core/rps_sock_flow_entries
# 设置每个队列的流表大小
echo 2048 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt
7.4 调整文件描述符限制
编辑 /etc/security/limits.conf:
* soft nofile 65536
* hard nofile 65536
* soft nproc 32768
* hard nproc 32768
编辑 /etc/sysctl.conf:
ini# 系统级文件描述符限制
fs.file-max = 6553560
使配置生效:
bashsysctl -p
重新登录生效。
7.5 调整内核参数
编辑 /etc/sysctl.conf:
ini# 增加最大连接数
net.core.somaxconn = 32768
# 增加 TCP 连接队列
net.ipv4.tcp_max_syn_backlog = 8192
# 启用 TCP 时间戳
net.ipv4.tcp_timestamps = 1
# 启用 TCP 窗口扩展
net.ipv4.tcp_window_scaling = 1
# 减少 TIME_WAIT 状态连接数
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
# 增加本地端口范围
net.ipv4.ip_local_port_range = 10000 65000
使配置生效:
bashsysctl -p
八、日志或指标观察方法
8.1 系统日志
bash# 查看系统日志最后 50 行
journalctl -xe | tail -50
# 查看内核日志
dmesg | tail -50
# 持续监控系统日志
journalctl -f
关注关键字:
Out of memory:内存不足I/O error:磁盘 IO 错误segfault:进程段错误hung task:进程卡死soft lockup:软锁死hard lockup:硬锁死
8.2 应用日志
根据应用不同,日志路径不同。常见路径:
- Nginx:
/var/log/nginx/error.log - Apache:
/var/log/httpd/error_log - MySQL:
/var/log/mysql/error.log - Redis:
/var/log/redis/redis-server.log - PHP-FPM:
/var/log/php-fpm/error.log
8.3 监控指标
如果使用 Prometheus + Grafana 监控,重点关注:
node_load1、node_load5、node_load15:Load Averagenode_cpu_seconds_total:CPU 使用时间node_memory_MemAvailable_bytes:可用内存node_memory_SwapCached_bytes:Swap 使用量node_disk_io_time_seconds_total:磁盘 IO 时间node_disk_read_bytes_total:磁盘读字节数node_disk_written_bytes_total:磁盘写字节数node_network_receive_bytes_total:网络接收字节数node_network_transmit_bytes_total:网络发送字节数
以上指标名称仅供参考,实际指标名称取决于使用的 exporter 版本。
九、排查路径
以下是几种典型场景的完整排查路径。
场景 1:Load Average 高且 CPU 使用率高
步骤 1:uptime 确认负载高
步骤 2:top 确认 CPU 使用率高
步骤 3:ps aux --sort=-%cpu 找出 CPU 占用最高的进程
步骤 4:lsof -p <PID> 查看进程打开的文件和连接
步骤 5:strace -p <PID> -c 查看系统调用
步骤 6:分析进程行为,确认是否正常
步骤 7:如果是计算密集型任务,考虑优化代码或扩容
步骤 8:如果是异常进程,考虑重启或 kill
步骤 9:验证负载是否恢复
场景 2:Load Average 高但 CPU 空闲
步骤 1:uptime 确认负载高
步骤 2:top 确认 CPU idle 高但 wa 也高
步骤 3:iostat -x 1 5 确认磁盘 IO 瓶颈
步骤 4:iotop -o 找出 IO 占用最高的进程
步骤 5:lsof -p <PID> 查看进程访问的文件
步骤 6:检查是否有大文件操作、备份任务等
步骤 7:如果是日志写入过多,考虑调整日志级别或轮转策略
步骤 8:如果是数据库慢查询,优化 SQL 或加索引
步骤 9:验证负载是否恢复
场景 3:有多个 D 状态进程
步骤 1:ps aux | awk '$8 ~ /D/ {print $0}' 找出 D 状态进程
步骤 2:cat /proc/<PID>/stack 查看进程堆栈
步骤 3:确认进程卡在哪个系统调用上
步骤 4:如果是磁盘 IO,检查磁盘健康状态
步骤 5:如果是 NFS 挂载,检查网络和 NFS 服务
步骤 6:尝试强制卸载或重启相关服务
步骤 7:如果无法解决,可能需要重启系统
场景 4:软中断过高
步骤 1:top 确认 si 占比很高
步骤 2:cat /proc/softirqs 确认是网络软中断
步骤 3:sar -n DEV 1 5 确认网络流量很大
步骤 4:netstat -antp 或 ss -antp 查看网络连接
步骤 5:找出占用网络最多的进程
步骤 6:ethtool -l eth0 查看网卡队列配置
步骤 7:启用网卡多队列、RPS、RFS
步骤 8:验证软中断是否下降
场景 5:内存不足频繁 swap
步骤 1:free -h 确认内存不足且 swap 使用率高
步骤 2:vmstat 1 5 确认有频繁的 si 和 so
步骤 3:ps aux --sort=-%mem 找出内存占用最高的进程
步骤 4:分析进程内存使用是否合理
步骤 5:考虑优化应用内存使用或扩容内存
步骤 6:临时清理缓存缓解(慎用)
步骤 7:调整 swappiness 参数
步骤 8:验证 swap 使用率是否下降
十、风险提醒
10.1 清理缓存风险
执行 echo 3 > /proc/sys/vm/drop_caches 会清理 page cache、dentries 和 inodes,可能导致:
- 后续文件 IO 变慢,需要重新从磁盘读取
- 正在进行的 IO 操作可能受影响
- 数据库性能短时间内下降
建议:
- 生产环境慎用
- 仅在内存极度紧张且确认缓存占用过多时使用
- 在业务低峰期执行
10.2 强制 kill 进程风险
使用 kill -9 <PID> 强制杀掉进程可能导致:
- 数据丢失或损坏
- 锁文件未清理
- 子进程变成孤儿进程
- 服务无法正常重启
建议:
- 优先使用
kill <PID>让进程优雅退出 - 确认业务影响和重启方案
- 检查是否有备份
10.3 强制卸载文件系统风险
使用 umount -f 或 umount -l 强制卸载文件系统可能导致:
- 正在访问该文件系统的进程崩溃
- 数据丢失
- 文件系统损坏
建议:
- 优先确认没有进程在使用该文件系统
- 使用
lsof /mnt/path或fuser -m /mnt/path查看使用情况 - 考虑先停止相关服务
10.4 调整内核参数风险
修改 /etc/sysctl.conf 中的内核参数需要谨慎,错误的参数可能导致:
- 系统不稳定
- 网络连接异常
- 性能下降
建议:
- 先在测试环境验证
- 修改前备份原配置
- 逐个参数调整并观察效果
- 记录修改原因和预期效果
10.5 重启服务风险
重启服务可能导致:
- 业务中断
- 用户请求失败
- 数据丢失
建议:
- 先评估业务影响
- 选择业务低峰期操作
- 提前通知相关人员
- 准备回滚方案
- 监控服务重启后状态
十一、验证方式
11.1 验证负载是否恢复
bashuptime
# 观察 Load Average 是否下降到正常范围
连续观察几分钟,确认负载持续下降或保持稳定。
11.2 验证 CPU 使用率是否正常
bashtop
# 观察 %Cpu(s) 行的 id 值是否上升
# 观察 wa、si 等值是否下降
11.3 验证内存使用是否改善
bashfree -h
# 观察 available 内存是否增加
# 观察 swap 使用量是否下降
11.4 验证磁盘 IO 是否缓解
bashiostat -x 1 5
# 观察 %util 是否下降
# 观察 await 是否下降
11.5 验证网络流量是否正常
bashsar -n DEV 1 5
# 观察 rxpck/s 和 txpck/s 是否恢复正常水平
11.6 验证软中断是否下降
bashtop
# 观察 %Cpu(s) 行的 si 值是否下降
11.7 验证进程状态是否正常
bashps -eo stat | sort | uniq -c | sort -rn
# 观察 D 状态进程是否减少
# 观察 R 状态进程是否在合理范围
11.8 验证业务是否恢复
- 检查应用日志是否还有大量错误
- 检查用户反馈是否恢复正常
- 检查监控面板是否恢复正常
- 进行业务功能验证
十二、回滚方案
12.1 内核参数调整回滚
如果修改 /etc/sysctl.conf 后系统异常,回滚方法:
bash# 恢复备份的配置文件
cp /etc/sysctl.conf.bak /etc/sysctl.conf
# 使配置生效
sysctl -p
或者直接修改单个参数:
bash# 恢复 swappiness 为默认值
echo 60 > /proc/sys/vm/swappiness
12.2 网卡配置回滚
如果修改网卡队列或 RPS 配置后网络异常,回滚方法:
bash# 恢复网卡队列为默认值
ethtool -L eth0 combined 1
# 清空 RPS 配置
echo 0 > /sys/class/net/eth0/queues/rx-0/rps_cpus
12.3 服务重启回滚
如果重启服务后问题更严重,回滚方法:
- 如果有服务版本管理,回滚到上一个稳定版本
- 如果有配置文件备份,恢复旧配置
- 如果有数据备份,恢复数据
- 如果有完整的快照,考虑从快照恢复
12.4 进程 kill 回滚
如果 kill 进程后发现影响业务,回滚方法:
bash# 重新启动进程
systemctl start <service_name>
# 或者手动启动
/path/to/binary &
确认服务启动后:
- 检查进程是否正常运行
- 检查日志是否有错误
- 验证业务功能
十三、生产环境注意事项
13.1 操作前检查
- 确认当前是否业务高峰期
- 确认是否有重要任务正在执行
- 确认是否有备份
- 确认回滚方案是否可行
- 确认相关人员是否知晓
13.2 操作中监控
- 持续观察监控面板
- 持续观察应用日志
- 持续观察系统日志
- 准备随时回滚
13.3 操作后验证
- 验证负载是否恢复
- 验证业务是否正常
- 验证监控是否正常
- 记录操作过程和结果
13.4 权限控制
- 生产环境操作需要审批
- 重要操作需要双人确认
- 记录操作日志
- 避免直接使用 root 用户
13.5 变更管理
- 遵循变更流程
- 记录变更内容
- 记录变更原因
- 记录变更影响
- 记录回滚方案
13.6 应急预案
- 准备应急联系人列表
- 准备应急处理流程
- 准备常用命令清单
- 定期演练应急流程
十四、总结
排查 Linux 系统负载过高问题是运维工程师的基本功,需要掌握以下几点:
14.1 理解核心概念
- Load Average 反映的是可运行和不可中断睡眠状态的进程数
- 需要结合 CPU 核心数判断负载是否正常
- Load Average 高不一定是 CPU 高,也可能是 IO 瓶颈
14.2 建立排查路径
- 先整体后局部
- 先观察后操作
- 先排除明显问题
- 先非侵入后侵入
- 记录现场
14.3 熟练使用工具
uptime、top、htop:查看负载和 CPUfree、vmstat:查看内存和 swapiostat、iotop:查看磁盘 IOsar、netstat、ss:查看网络ps、lsof、strace、pstack:分析进程
14.4 掌握分析方法
- 根据 CPU、内存、磁盘、网络四大资源分类排查
- 关注进程状态分布,重点关注 R 和 D 状态
- 深入分析异常进程的系统调用、打开文件、网络连接
- 综合多个指标判断根因
14.5 采取有效措施
- 临时措施:降低优先级、清理缓存、限速等
- 根本措施:优化代码、调整配置、扩容资源
- 高风险操作需要评估影响、准备回滚
- 生产环境操作需要遵循变更流程
14.6 形成闭环
- 修复后必须验证效果
- 准备回滚方案
- 记录排查过程和结果
- 形成故障报告和知识沉淀
- 优化监控告警和预防机制
只有经过大量实战积累,才能在生产环境故障时快速定位问题、采取正确措施、恢复业务正常。本文提供的是系统化的排查思路和工具方法,需要结合具体业务场景和系统特点灵活运用。

本文链接:https://www.yunweipai.com/archives/49403




网友评论comments