在香港CN2 VPS上看到这样一个画面,很难不让人困惑:top命令第一行显示负载已经飙到十几甚至几十,但下面那行CPU使用率里,id(空闲)却还挂着百分之八九十。负载都这么高了,CPU怎么还在“闲着”?是不是监控坏了,还是这台机器有什么暗病?
这个矛盾之所以让人反复纠结,是因为绝大多数人默认把“负载”当成了“CPU使用率”的另一个说法。实际上,在Linux内核的统计逻辑里,这两个数字衡量的根本不是同一件事。它们可以在极端情况下完全脱钩:CPU闲得发慌,负载却高得吓人。香港CN2线路在这里扮演的角色,往往不是原因,而是一个容易让人误判方向的背景板——线路本身是通的,延迟也不高,问题出在服务器内部另一套资源上。
负载统计的到底是什么?
要理解这个现象,得先看一眼Linux内核是怎么算负载的。/proc/loadavg里那三个数字,对应的不是CPU时间片的占用比例,而是处于“可运行状态”和“不可中断睡眠状态”的进程数量,经过指数衰减平均之后得到的值。
可运行状态好理解:进程在排队等CPU,或者正在CPU上跑着。如果一个四核机器上负载是4.0,意味着刚好每个核心都摊到一个进程,没有额外排队。超过4,就开始有人等着了。
关键在于第二类:不可中断睡眠状态,也就是ps命令里STAT列显示为D的那些进程。这类进程不在跑,也不在排队等CPU,它们卡在内核的某个流程里,等待一个硬件操作完成——最常见的就是磁盘I/O。内核把这种进程也计入负载,理由是:虽然它没在消耗CPU,但它占着一个“任务槽位”,系统资源被它牵制着,不能当作不存在。
CPU使用率统计的是另一回事
在采样周期内,CPU的时间到底花在了哪里。us是用户态程序,sy是内核态,wa是等I/O,id是空闲。这里有一个极其容易混淆的地方:wa只统计CPU因为等待I/O而“空转”的那部分时间,但一个卡在D状态的进程,内核根本不会把它算进wa里。因为该进程已经进入了不可中断的睡眠,CPU并没有在“等”它,CPU只是无事可做,去跑别的任务或者干脆闲着了。
于是局面就变成了:大量进程卡在D状态等磁盘,内核把它们统统计入负载,负载数字一路飙升;但CPU确实没什么活干,id居高不下,wa可能也低得让人迷惑。一台香港VPS上跑着数据库或者大量小文件读写的应用,遇到磁盘性能瓶颈时,这个组合会非常典型地出现。
香港CN2在这个问题里扮演什么角色
必须说清楚一件事:CN2解决的是跨境数据传输的路径质量问题。它优化的是数据包从内地到香港机房这段路上的延迟、丢包和抖动。当你的SSH连上去敲命令反应很快,或者网页首字节返回得还算及时,说明CN2线路在正常工作。
但CN2管不到VPS内部的磁盘。一台香港VPS的存储性能取决于几个因素:底层是NVMe还是SATA SSD,是本地盘还是网络存储,以及最关键的——这台宿主机上超售有多严重。香港机房资源成本高,存储I/O的争抢往往比CPU超售更隐蔽。你看到的st(steal time)可能不高,CPU确实分到了时间片,但磁盘的IOPS被邻居虚拟机瓜分殆尽,你的进程一发起读写就卡进D状态,负载随之飙升。
还有一种香港VPS上不算罕见的情况:系统内存不足,开始用swap。物理内存耗尽后,内核把内存页换到磁盘上,下次访问再换回来。这个过程涉及磁盘I/O,相关进程同样会进入D状态。free -m里available接近零、swap的used不为零,就是明确的信号。CN2线路再好,也救不了一台在拿硬盘当内存用的机器。
把两个指标拆开看:各自在说什么
用一个不那么严谨但足够直观的类比。把VPS想象成一个厨房。CPU使用率衡量的是灶台的火有没有开着。负载衡量的是厨房里有多少人,要么在灶台前炒菜,要么堵在冰箱前面等着拿食材。冰箱(磁盘I/O)如果出了问题,一群人堵在冰箱门口,厨房里“人数”很多,负载很高,但灶台可能根本没开火,CPU使用率很低。
| 观察到的组合 | 更可能指向的方向 |
|---|---|
负载高,us或sy也高 |
进程在实打实地消耗CPU,考虑计算瓶颈或代码问题 |
负载高,us低,wa高 |
磁盘确实在拖慢CPU,CPU有等待动作 |
负载高,us低,wa也低,但D状态进程多 |
进程卡在不可中断的I/O里,负载被这类进程撑高 |
负载高,st也高 |
宿主机超售,CPU时间片被其他虚拟机抢走 |
最后一行需要单独提一句。st是虚拟化环境特有的指标。香港低价VPS超售是公开的秘密,你买的“2核”在晚高峰可能连半个核的实际算力都拿不到。st持续高于5%就是一个需要警惕的信号。这种情况下,负载高是因为你的进程在等CPU时间片,但CPU使用率统计的是“你实际拿到并消耗掉的时间”,被偷走的那部分不计入你的使用率。所以可能出现st高、负载高、us看起来不高的局面。这跟磁盘I/O导致的负载高是两回事,排查方向完全不同。
落地排查:从负载数字走到具体进程
看到负载高但CPU使用率低,第一步不是重启,也不是立刻升级配置。先确认D状态进程的规模。
ps -eLo stat | grep -c '^D' 这一条命令就能数出当前有多少进程卡在不可中断睡眠里。如果这个数字跟负载的量级大致对得上,问题方向基本锁定在I/O等待侧。
接着看这些进程卡在什么地方。ps -eLo pid,ppid,stat,wchan:32,comm,args | awk '$3 ~ /D/' 可以把D状态进程的等待通道(wchan)列出来。如果看到跟磁盘、文件系统、网络存储相关的内核函数,说明它们确实在等I/O。top命令默认不直接展示D状态进程,需要主动过滤或者用ps来看,这是很多人漏掉关键线索的原因。
然后确认磁盘本身的状态。iostat -x 1 看%util和await。如果设备利用率长期贴着100%,或者平均等待时间远超正常值,磁盘就是瓶颈所在。香港VPS上如果跑的是MySQL,SHOW FULL PROCESSLIST里那些Time很大、State显示Sending data或Copying to tmp table的查询,往往就是制造磁盘压力的源头。
内存也要同步扫一眼。free -m看available,vmstat 1看si和so是否持续非零。swap一旦开始频繁换入换出,磁盘压力会成倍放大,负载跟着往上走,而CPU使用率依然可能很低。
推荐文章