香港服务器出现高负载时,如何结合CPU、内存与磁盘I/O定位原因

“香港服务器出现高负载”并不等于 CPU 使用率达到了 100%。Linux 的 load average 同时统计处于可运行状态和不可中断睡眠状态的任务,后者经常与磁盘 I/O 等待有关。因此,单看负载数字无法判断是 CPU 不足、内存紧张、磁盘延迟,还是连接和进程堆积。
排查时应先记录同一时间窗口内的 load average、各核心 CPU 状态、内存与交换分区、磁盘队列、连接状态以及进程状态,再通过多个指标的变化是否同步来定位原因。一个简单入口是依次查看 uptime、vmstat、iostat、pidstat 和 ss,不要在没有证据时直接重启服务或终止高占用进程。
先明确“高负载”具体代表什么
负载平均值不是 CPU 百分比
执行以下命令可以查看系统运行时间、1 分钟、5 分钟和 15 分钟负载:
uptime
nproc
nproc 返回当前环境可见的逻辑 CPU 数量。判断负载时,需要把 load average 与 CPU 数量放在一起看:
- 负载持续低于逻辑 CPU 数量,通常说明可运行任务没有长期排队,但不能排除某个单线程进程或磁盘等待。
- 负载持续高于逻辑 CPU 数量,说明系统中的可运行任务或不可中断任务存在排队,需要继续区分 CPU 竞争和 I/O 阻塞。
- 负载短时间升高后迅速恢复,可能只是业务突发,不足以证明服务器容量长期不足。
- 负载升高但 CPU 使用率不高时,应优先检查
iowait、磁盘队列以及处于D状态的进程。
负载平均值具有平滑特征,故障解除后不会立即回到原水平。复测时要同时观察实时采样结果,而不能只等待 uptime 中的 1 分钟负载下降。
指标各自能证明什么
| 指标 | 主要含义 | 能支持的判断 | 不能单独证明的结论 |
|---|---|---|---|
load average | 可运行或不可中断任务的平均数量 | 系统是否存在任务排队 | 不能单独证明 CPU 不足 |
us、sy | 用户态和内核态 CPU 时间 | 应用计算或系统调用是否消耗 CPU | 不能直接说明哪个请求最慢 |
wa | CPU 等待 I/O 的时间比例 | 是否存在明显 I/O 等待 | 不能单独证明磁盘已损坏或达到极限 |
free -h 的 available | 内核估算的可用内存 | 是否存在内存压力 | 不能只根据 free 数值判断内存不足 |
vmstat 的 si、so | 交换分区换入、换出 | 是否发生持续 Swap 活动 | Swap 已使用不代表当前一定有内存故障 |
iostat 的 await、队列和利用率 | 设备延迟与排队情况 | 存储请求是否受延迟影响 | 单个设备利用率高不等于应用一定被磁盘限制 |
ss 的连接状态 | TCP 连接生命周期和监听队列 | 连接是否大量堆积或关闭不及时 | 连接数多不等于服务器必然高负载 |
进程 STAT | 进程当前运行、睡眠或阻塞状态 | 任务是在消耗 CPU 还是等待资源 | 单次进程状态不能代表持续趋势 |
先完成一次低风险采样
以下命令适用于常见 Linux 环境,主要用于读取系统状态,不会修改服务配置。iostat 和 pidstat 通常由 sysstat 提供;如果系统没有这些命令,应先确认软件包来源和安装影响,不要在故障高峰期随意执行不熟悉的安装脚本。
date
uptime
nproc
free -h
swapon --show
vmstat 1 5
iostat -xz 1 5
pidstat -u -r -d -p ALL 1 5
ss -s
ss -lntp
采样时应记录业务异常发生的时间,并尽量在异常持续期间执行。vmstat 和 iostat 的首行可能是自系统启动以来的累计统计,重点观察后续按秒输出的区间数据。若只执行一次命令,只能得到瞬时状态,无法判断指标是否持续。
如果当前服务器安装了监控系统,还应把应用响应时间、错误率、请求量与上述系统指标按时间对齐。系统指标可以说明资源在哪里等待,但通常不能单独说明哪个接口或哪类请求触发了问题。
从 CPU 指标判断是否属于计算型高负载
先看所有逻辑 CPU 是否均衡,以及用户态、内核态和 I/O 等待的比例:
mpstat -P ALL 1 5
如果没有 mpstat,可以使用:
top
重点关注以下情况:
us持续较高,且某个应用进程或线程的 CPU 使用率同步升高,通常更接近应用计算、循环处理或并发请求导致的 CPU 型负载。sy较高,说明 CPU 时间更多消耗在内核态,可能与大量系统调用、网络收发、进程切换或存储访问有关,需要结合进程和 I/O 数据判断。wa较高而id仍然存在,说明 CPU 并没有一直进行计算,而是在等待 I/O。此时直接增加 CPU 资源未必能解决问题。- 总体 CPU 使用率不高,但某一个核心接近满载,可能是单线程任务、线程调度不均或某个进程只使用了部分核心。必须查看
mpstat -P ALL,不能只看总 CPU 百分比。 st较高时,表示虚拟化环境中的虚拟 CPU 受到调度影响。此时应用进程可能没有持续消耗 CPU,但仍然无法及时获得运行时间,需结合运行环境的资源限制进一步核验。
使用 pidstat 查看进程级 CPU 变化:
pidstat -u -p ALL 1 5
ps -eo pid,ppid,stat,comm,%cpu,%mem,rss,etime --sort=-%cpu | head -n 20
如果同一个进程在连续采样中保持较高 %CPU,同时系统的 us 或 sy 也同步升高,才可以把它列为 CPU 方向的主要嫌疑。单次 ps 排名只能说明某一时刻谁最忙,不能证明该进程就是根因。
用内存与 Swap 判断是否存在内存压力
内存排查首先看 available,而不是只看 free:
free -h
swapon --show
vmstat 1 5
ps -eo pid,ppid,stat,comm,%mem,rss,vsz,etime --sort=-rss | head -n 20
Linux 会把一部分空闲内存用于页缓存,因此 free 较小并不必然表示内存不足。更有参考价值的是:
available持续偏低,同时vmstat中si、so持续出现,说明系统正在频繁回收内存或使用交换分区。si、so与iostat中的磁盘读写、等待时间同时升高,说明内存压力可能已经转化为磁盘 I/O。此时不能只把磁盘延迟当成存储本身的问题。- 某个进程的 RSS 在多个采样点持续增长,且业务请求量没有同步变化,需要进一步检查进程缓存、连接生命周期或内存泄漏。
- Swap 已经配置并被使用,但当前
si、so没有持续活动,不能仅凭 Swap 使用量判定系统正处于严重内存压力。
如果怀疑发生过 OOM,可以在使用 systemd 的 Linux 系统上读取本次启动的内核日志:
journalctl -k -b --no-pager | grep -Ei 'oom|out of memory|killed process'
该命令只读取日志;如果当前账号无权访问内核日志,应使用具备相应权限的账号或由运维人员执行。发现 OOM 记录后,需要把被终止的进程、发生时间和当时的内存曲线对应起来,不能只根据当前的 free -h 结果倒推原因。
通过磁盘 I/O 区分延迟、吞吐与队列
磁盘问题不能只看“读写量大不大”。应结合设备等待时间、请求队列和产生 I/O 的进程:
iostat -xz 1 5
pidstat -d -p ALL 1 5
df -hT
df -i
iostat -xz 中常见字段可以这样理解:
r/s、w/s表示每秒读写请求数量,反映请求频率。rkB/s、wkB/s表示读写吞吐量,吞吐量高不一定意味着延迟高。await反映请求从提交到完成的大致等待时间,连续升高时应结合队列和业务响应时间判断。aqu-sz反映平均队列情况,持续增加通常说明请求处理速度跟不上到达速度。%util表示统计周期内设备处理请求的忙碌程度,但不同存储设备的并行处理能力不同,不能把某个固定百分比当成所有场景的绝对上限。
如果 vmstat 中 b 较多、wa 升高、iostat 的等待和队列也升高,同时 pidstat -d 显示某个进程持续读写,那么磁盘 I/O 是较有依据的排查方向。反之,只有 %util 较高而等待时间、队列和业务延迟都没有变化时,不能直接认定磁盘是瓶颈。
df -hT 用于确认文件系统容量,df -i 用于确认 inode 是否耗尽。磁盘空间或 inode 用尽会导致写入失败,但这和设备延迟过高是两类问题,处理方法也不同。不要为了“释放空间”直接删除日志或业务文件;涉及删除、压缩、覆盖前,应先确认文件归属、保留要求和恢复方式。
连接数与进程状态要结合起来看
查看 TCP 总体状态和监听 socket:
ss -s
ss -lntp
ss -tan | awk 'NR > 1 {print $1}' | sort | uniq -c | sort -nr
连接状态提供的是线索,不是结论:
ESTAB较多,说明当前存在较多已建立连接,但是否造成高负载还要看每个连接对应的进程、请求频率和内存占用。SYN-RECV持续堆积,可能表示连接建立速度超过应用接受速度,也可能与客户端重试、监听队列或网络状况有关,需要结合监听端口的Recv-Q变化确认。TIME-WAIT较多通常与大量短连接关闭有关,它本身不等于当前请求仍在执行。CLOSE-WAIT持续增加时,应检查拥有这些 socket 的进程是否及时关闭连接。它常提示应用连接管理异常,但不能只凭数量判断具体代码问题。ss -lntp中监听 socket 的接收队列持续增长,说明连接已经到达监听端口,但应用接受或处理速度可能不足。
进一步查看进程状态:
ps -eo pid,ppid,stat,wchan:32,comm,%cpu,%mem --sort=-%cpu | head -n 20
常见状态包括:
R:正在运行或等待运行,多个采样点持续出现时,更支持 CPU 竞争或任务排队的判断。D:不可中断睡眠,常见于等待 I/O。若与wa、await、磁盘队列同步升高,I/O 关联更可信。S:可中断睡眠,很多正常服务进程在空闲时都会处于该状态,不能视为故障。Z:僵尸进程,通常不再消耗正常运行所需的 CPU 和内存,但数量持续增加说明父进程回收子进程存在问题。
wchan 可以辅助判断进程正在等待什么,但不同内核、权限和编译选项下显示内容可能不同,因此只能作为辅助信息,不能单独依赖其名称下结论。
用多个指标组合定位方向
下面的组合比单个指标更有判断价值:
| 观察组合 | 更可能的方向 | 需要继续验证的内容 |
|---|---|---|
负载持续升高,多个核心繁忙,us 或 sy 较高,某进程 CPU 占用同步升高 | CPU 型负载 | 该进程的线程、请求量和业务操作是否同步变化 |
负载升高,wa 增加,D 状态任务增多,await 和队列同步升高 | 磁盘 I/O 等待 | 哪个进程产生读写,是否由日志、缓存、数据库文件或其他业务文件触发 |
available 偏低,si、so 持续出现,磁盘读写和等待也升高 | 内存压力引发的交换 I/O | RSS 持续增长的进程、内核日志和内存使用趋势 |
CPU 不一定很高,但 SYN-RECV、监听 Recv-Q 或 CLOSE-WAIT 持续增加 | 连接建立、接受或关闭处理异常 | 监听进程、应用连接池、超时设置和请求处理时间 |
| 负载升高,但 CPU、内存、磁盘和连接指标都很快恢复正常 | 短时突发或采样错位 | 业务请求时间线、定时任务和更长时间窗口的监控数据 |
| 主机指标正常,但某服务响应明显变慢 | 服务级限制或应用内部排队 | 服务进程所在的 cgroup 限制、线程池、连接池和应用自身指标 |
表中的“更可能”不是最终结论。可靠定位至少需要两个相互独立的指标相互印证,例如不能只凭高负载判断 CPU 不足,也不能只凭磁盘利用率判断存储延迟是根因。
复测、验证与容量判断边界
定位过程中可以按以下方式完成复测:
- 在异常仍然存在时记录时间、业务现象和第一轮采样结果,保留原始输出,不要先清理现场。
- 连续执行多个采样周期,比较
vmstat的r、b、si、so,iostat的等待和队列,以及pidstat的进程变化。 - 找到资源指标与进程、连接或业务请求同时变化的证据后,再选择低风险的应用参数调整或业务降载措施。
- 变更后重新采样,确认对应指标、服务响应时间和错误率是否同步改善。只看负载平均值下降,不足以证明问题已经解决。
- 如果必须重启服务或终止进程,应先确认进程归属、依赖关系、数据写入状态和恢复方式;优先使用服务自身的优雅退出机制,避免在没有证据留存和回滚方案时执行强制终止。
判断是否需要扩容或调整资源,也不能根据一次高峰或一个数字决定。只有在多个业务高峰中,CPU 运行队列与进程 CPU 消耗稳定对应,才适合把 CPU 作为容量瓶颈;只有在可用内存持续下降、Swap 活跃或出现 OOM 证据时,才应把内存作为主要容量方向;只有在 I/O 等待、队列、进程读写和业务延迟长期同步时,才适合把磁盘性能作为主要处理方向。
如果复测后只有连接数增加,而 CPU、内存和磁盘指标均未出现资源压力,应优先检查连接处理效率,而不是简单提高连接上限。反过来,如果连接数、CPU、内存和 I/O 同时上升,则需要根据时间先后关系判断是请求量先增加,还是某个进程异常导致连接无法及时释放。通过这种交叉验证,才能把“香港服务器高负载”从一个笼统现象,缩小到可以执行和复核的资源问题。