配置相同的美国服务器为何晚高峰更卡?如何联动网络与资源指标判断瓶颈?
配置相同的美国服务器,晚高峰表现仍可能明显不同。CPU 核数、内存容量和磁盘规格只说明了服务器拥有多少计算资源,并不能说明网络出口是否拥塞、TCP 是否重传、宿主机是否存在资源争用,也不能说明应用线程池、连接池和数据库查询是否在同一时间排队。
判断“为什么你的美国服务器晚高峰很卡”,不要先盯着某一个 CPU 百分比或某一次 ping 结果。更可靠的做法是把晚高峰和非高峰放进同一时间轴,同时观察用户请求耗时、网络吞吐与丢包、CPU 调度、内存压力、磁盘等待、应用队列和数据库等待。至少有两类指标在同一时间发生变化,并且能够排除替代解释,才适合认定瓶颈位置。
一、先建立可比较的观察窗口
1. 准备前置条件
以下示例以常见 Linux 服务器为基础,命令主要用于读取状态,不会修改系统配置。执行前准备:
- 一个能够代表真实业务的访问地址或健康检查接口。
- 一台或多台代表性客户端,用于从用户侧记录连接、首字节和完整响应耗时。
- 服务器的系统时间、应用日志时间和监控时间保持一致,至少记录时区。
- 明确本次观察的服务器公网 IP、业务域名、监听端口和网络接口名称。
- 确认是否使用了反向代理、应用进程、连接池和数据库,并记录当前版本与配置变更时间。
- 避免在晚高峰直接进行压力测试。诊断请求应采用低频、固定路径和固定请求参数。
先确认系统和工具是否存在:
cat /etc/os-release
date '+%F %T %Z'
nproc
ip route
command -v mpstat
command -v vmstat
command -v iostat
command -v pidstat
command -v sar
command -v ss
command -v ethtool
command -v ping
command -v traceroute
command -v mtr
mpstat、iostat、pidstat 和 sar 通常由 sysstat 提供。缺少工具时,应在业务低峰或维护窗口通过当前系统的软件源安装,并记录软件包变更;不要为了临时排查在高峰期执行系统升级。
2. 选择两个以上对照窗口
建议至少记录三次非高峰窗口和三次晚高峰窗口,每次连续观察 15~30 分钟。每个窗口使用相同的:
- 业务接口和请求参数;
- 客户端或客户端网络环境;
- 采样间隔;
- 统计口径,例如 p50、p95、p99;
- 时间基准。
只记录某一分钟的峰值,容易把一次垃圾回收、单个慢查询或偶发路由抖动误判为持续瓶颈。更有价值的是比较同一时间段内的变化趋势,例如晚高峰开始后,p95 是否先上升,随后网络重传增加,还是应用队列先增长。
客户端可以使用只读请求记录各阶段耗时:
curl -sS -o /dev/null \
-w 'dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total} bytes=%{size_download}\n' \
'https://your-domain.example/health'
这里的地址应替换为真实业务接口。固定使用同一个接口,避免一个请求命中缓存、另一个请求执行完整业务逻辑。
这些字段可初步这样理解:
| 指标 | 变慢时更值得怀疑的方向 | 不能单独证明的事情 |
|---|---|---|
| DNS 时间 | DNS 解析或客户端解析链路 | 不能证明服务器 CPU 瓶颈 |
| connect 时间 | TCP 建连、连接队列、网络路径 | 不能单独证明出口拥塞 |
| TLS 时间 | 握手计算、连接复用变化或网络抖动 | 不能直接证明应用代码慢 |
| TTFB | 服务端处理、应用队列、数据库等待 | 不能排除请求已经在网络连接阶段等待 |
| total 与 TTFB 的差值 | 响应传输、客户端接收或网络拥塞 | 不能直接证明服务器磁盘慢 |
例如,TTFB 从 200 毫秒上升到 1 秒,通常应先查看应用、数据库和服务器排队;如果 TTFB 基本不变,但 total 从 1.2 秒升到 5 秒,同时响应体大小和出口流量接近上限,则网络传输更可疑。
二、先看用户请求,再对齐服务器指标
用户看到的“卡”可能包含连接慢、服务端处理慢和响应下载慢三部分。必须把客户端结果与服务器同一时间段的指标对齐,不能只在服务器上执行一次 curl 就下结论。

1. 记录服务器端请求耗时
如果业务已经有应用监控,优先使用应用的请求耗时、并发请求数、工作线程忙碌度、队列长度和错误率。如果使用 Nginx 作为反向代理,可以临时记录请求总耗时和上游响应耗时。
先确认配置位置:
sudo nginx -t
sudo nginx -T 2>/dev/null | grep -nE 'log_format|access_log'
在确认 Nginx 配置结构后,可以在已有的 http {} 配置段中增加独立的日志格式。不要覆盖已有格式,也不要把下面内容直接放到不兼容的配置段中:
log_format perf_timing
'$time_iso8601 request="$request" status=$status '
'request_time=$request_time '
'upstream_response_time=$upstream_response_time '
'bytes_sent=$bytes_sent';
access_log /var/log/nginx/access.log perf_timing;
应用这类变更前,先备份实际配置文件,并检查语法:
sudo cp -a /etc/nginx/nginx.conf \
"/etc/nginx/nginx.conf.bak-$(date +%F-%H%M%S)"
sudo nginx -t
sudo systemctl reload nginx
成功验证包括:
sudo nginx -t
sudo tail -n 20 /var/log/nginx/access.log
如果 request_time 很高,而 upstream_response_time 也同步升高,应用或数据库等待更值得怀疑。如果 upstream_response_time 较低,但 request_time 明显更长,可能是响应发送、客户端接收或网络路径出现问题。静态文件请求的 upstream_response_time 可能为空,不能按应用请求处理。
2. 记录业务错误和队列
在同一时间轴中加入:
- HTTP 5xx、超时和连接重置数量;
- 应用工作线程忙碌数;
- 请求队列长度;
- 数据库连接池使用数和等待数;
- 每个接口的 p95、p99;
- 响应体平均大小;
- 单位时间请求数。
错误率上升而资源利用率不高,可能是依赖服务、连接池、超时配置或应用异常;错误率不变但 p99 上升,通常说明部分请求发生了排队或长尾等待。不能因为 CPU 只有 40% 就认为服务器没有瓶颈,单线程应用、锁等待和外部依赖都可能让整体 CPU 看起来不高。
三、判断网络瓶颈:把 ping、路由、TCP 和出口流量放在一起
配置相同的美国服务器,网络表现不同,常见原因包括实际出口带宽或每秒包数限制不同、上游路径在晚高峰拥塞、宿主机或共享网络设备发生争用、服务器网卡队列丢包,以及客户端到服务器的路径变化。
1. 找到业务目标使用的网络接口
不要默认接口一定叫 eth0。先根据实际业务目标查询路由:
TARGET=203.0.113.20
ip route get "$TARGET"
IFACE=$(ip route get "$TARGET" | \
awk '{for (i=1; i<=NF; i++) if ($i=="dev") {print $(i+1); exit}}')
echo "interface=$IFACE"
TARGET 应替换为经过授权的业务客户端地址、业务依赖地址或明确的服务端目标。不要通过批量探测陌生地址来判断线路。
2. 查看接口错误、丢包和队列
ip -s link show dev "$IFACE"
sar -n DEV 1 5
tc -s qdisc show dev "$IFACE"
重点关注:
- RX/TX errors;
- RX/TX dropped;
- qdisc 的 dropped、overlimits;
- 接收和发送速率;
- 晚高峰前后这些计数器的增长速度。
累计计数器本身没有意义,应该记录开始值和结束值,用“增长量除以观察秒数”得到变化速率。接口流量高也不等于已经拥塞,必须同时查看实际带宽上限、队列丢弃、TCP 重传和请求耗时。
如果系统允许查看驱动统计,可执行:
sudo ethtool -S "$IFACE" | \
grep -Ei 'drop|discard|error|timeout|pause|buffer|miss'
不同驱动暴露的字段名称不一致,不能因为某个字段不存在就判断没有丢包,也不能把所有字段都当作同一含义。
3. 使用 ping 判断时延和抖动,但不要把它当作唯一证据
ping -c 20 -W 2 "$TARGET"
重点看:
- 最小、平均和最大 RTT;
- RTT 的离散程度;
- 丢包比例;
- 晚高峰与非高峰的差异。
如果客户端访问服务器时变慢,最好从代表性客户端向服务器执行测试;只从服务器向外 ping,并不能完整代表用户到服务器的入站路径。
ping 的限制也必须明确:
- ICMP 可能被限速或低优先级处理;
- 中间路由器可能不响应,但不转发业务包;
- ping 正常不代表 TCP 建连、TLS 握手和 HTTP 响应正常;
- ping 变慢只能说明探测路径的时延变化,不能直接证明服务器 CPU 或网卡已经饱和。
4. 使用 traceroute 观察路径变化,但重点看终点
traceroute -n -q 3 -w 1 "$TARGET"
如果没有 traceroute,可在维护窗口安装与当前发行版匹配的诊断工具,或使用已有的 mtr:
mtr -n -r -c 100 "$TARGET"
traceroute 的关键用途是对比非高峰和晚高峰的路径、终点 RTT 以及是否出现持续的终点丢包。某个中间跳出现 *,并不等于业务流量在那里丢失,因为很多路由器会限制 TTL 超时报文的响应。只有当中间跳和后续多个跳都表现出相似的异常,并且终点也有对应变化,才更值得怀疑路径问题。
5. 查看 TCP 重传和连接状态
sar -n TCP,ETCP 1 5
ss -s
ss -lnt
nstat -az 2>/dev/null | \
grep -Ei 'TcpRetransSegs|TCPTimeouts|TCPBacklogDrop|TCPRcvQDrop'
需要关注:
- active/passive opens 是否在高峰突增;
- retrans、timeout 是否随 p95 同步增加;
- 监听 socket 的
Recv-Q是否持续接近或超过Send-Q; - TCP 连接数是否异常增长;
- 大量连接是否集中在某个状态;
- 重传增加时,接口或 qdisc 是否同时出现丢弃。
TCP 重传不是网络拥塞的单一证明,也可能由接收端处理不及时、队列溢出或对端异常造成。只有当重传、RTT、网络队列、出口流量或终端响应时间在同一窗口共同变化时,网络瓶颈的判断才更可靠。
四、排除 CPU 瓶颈:不要只看总利用率
使用多核服务器时,整体 CPU 利用率可能只有 40%,但单个核心已经跑满,应用仍然会排队。执行:
mpstat -P ALL 1 10
vmstat 1 10
pidstat -u -p ALL 1 10
mpstat 重点看每个 CPU 的 %usr、%sys、%iowait 和 %steal:
%usr持续较高,通常表示应用计算量增加;%sys持续较高,可能与网络包处理、系统调用或内核工作有关;%iowait较高,不能直接算 CPU 不足,应转向磁盘或存储等待;%steal在虚拟机中持续升高,说明虚拟 CPU 可能等待宿主机调度;- 单个核心接近 100%,而其他核心空闲,说明可能存在单线程、线程绑定或锁竞争。
vmstat 中的 r 是可运行队列,b 是不可中断等待任务数。r 长时间接近或超过可用 CPU 数量,同时用户请求 p95 上升,才支持 CPU 调度压力的判断。不能用“load average 大于 1”这种固定规则判断所有服务器,因为 2 核、8 核和 32 核的解释不同。
一个典型的 CPU 瓶颈组合是:
- p95 和 p99 在晚高峰同步上升;
- 一个或多个 CPU 核心长期接近满载;
r队列明显增加;%steal不高;- 磁盘 await、网络丢包和数据库等待没有同步恶化;
- 应用线程忙碌度接近上限。
如果只有总 CPU 高,但应用队列、响应时间和错误率没有变化,可能只是正常吞吐增加,不能直接认定故障。
五、判断内存压力:看回收、换页和 PSI
Linux 将空闲内存用于文件缓存,因此 free 较低不一定代表内存不足。先记录:
free -h
vmstat 1 10
cat /proc/pressure/memory
swapon --show
需要结合观察:
available是否持续下降;si、so是否持续出现,表示换入换出;- memory PSI 的
some或full是否在晚高峰升高; - 是否出现 OOM、进程被杀或频繁重启;
- 应用进程常驻内存是否随请求量持续增长;
- 数据库缓存、应用缓存和连接数是否在高峰达到上限。
如果 free 很少,但 available 充足、没有换页、PSI 稳定,通常不能仅凭“free 小”判断内存瓶颈。相反,应用 p95 上升、si/so 增加、memory PSI 上升,并伴随磁盘读写增加时,内存压力就可能间接转化为磁盘等待。
不要为了让 free 看起来变大而随意清理缓存,也不要在没有评估的情况下关闭 swap。此类操作会改变缓存和内存回收行为,甚至触发更严重的抖动。若确需调整内存参数,应先备份当前配置,记录变更时间,低峰验证,失败时恢复原值并重新加载配置。
六、判断磁盘和 I/O 瓶颈:看等待与队列,而不是只看磁盘容量
检查设备延迟、队列和吞吐:
iostat -xz 1 10
pidstat -d 1 10
df -hT
df -ih
重点关注:
await是否在晚高峰明显增加;aqu-sz或设备队列是否持续积压;%util是否接近设备在当前工作负载下的处理能力;rkB/s、wkB/s是否随业务请求同步增加;pidstat -d是否能定位到具体进程;- 文件系统容量或 inode 是否接近耗尽。
磁盘指标不能套用一个适用于所有设备的固定阈值。不同虚拟磁盘、SSD 和存储后端的并发处理能力不同。更可靠的组合是:应用响应变慢,%iowait 上升,iostat 的 await 与队列增加,具体进程的读写量同步变化。
如果 await 很高但 %util 不高,可能存在远端存储延迟、单线程 I/O、请求粒度过大或设备统计口径差异。此时不要直接把问题归为“磁盘带宽不够”,还要对照应用读写模式和数据库等待。
磁盘容量问题和磁盘性能问题也要分开:
- 容量接近满,可能导致日志、临时文件或数据库写入失败;
- inode 耗尽,可能无法创建新文件,即使仍有剩余空间;
- 性能变慢,主要体现为 await、队列、iowait 和应用等待增加。
七、把应用和数据库等待从资源瓶颈中区分出来
1. 应用线程池或连接池排队
应用层常见的瓶颈不是 CPU 或磁盘,而是并发控制参数达到上限。例如:
- 工作线程全部忙碌,新的请求进入队列;
- 数据库连接池已满,请求等待连接;
- 下游调用超时,线程被长时间占用;
- 锁竞争导致线程处于等待状态;
- 单个慢接口拖住共享线程池。
判断时要把“请求排队时间”和“实际执行时间”分开。一个接口的 TTFB 增加,如果应用队列等待明显增加,而 CPU、磁盘、网络都正常,应用并发模型更可疑。
不要在没有记录当前值的情况下盲目增大线程数或连接池。线程数增加可能带来更多上下文切换,连接池增加可能把压力转移到数据库,最终使晚高峰更不稳定。
2. 数据库连接、锁和慢查询
数据库瓶颈应至少同步查看:
- 活跃连接数与连接池上限;
- 等待连接数和连接池等待时间;
- 执行中的查询数;
- 锁等待时间;
- 慢查询数量和 p95;
- 数据库自身 CPU、内存和磁盘等待;
- 查询返回数据量是否在晚高峰变大。
“数据库连接数高”不等于数据库已经故障。有些连接处于空闲状态,有些连接虽然活跃但执行很快。更有价值的证据是:应用请求 p95 上升,同时连接池等待或锁等待增加,数据库慢查询时间也同步增加。
数据库问题还可能表现为服务器 CPU 不高、网络流量不高,但应用 TTFB 明显上升。这是因为线程正在等待数据库结果,而不是消耗本机 CPU。相反,如果数据库查询时间稳定,应用队列却增加,应优先回到应用线程池、锁和下游调用继续排查。
八、用联动数据形成判断
下面是一组模拟监控数据,用于说明判断方法,不代表某台服务器的实测结果。对比窗口均为 15 分钟。
| 场景 | 晚高峰 p95 | CPU/调度 | 内存 | 磁盘 | 网络 | 应用/数据库 | 更可能的瓶颈 |
|---|---|---|---|---|---|---|---|
| 场景 A | 180ms → 1.2s | 总体 35%,无单核满载 | PSI 稳定,无换页 | await 5ms → 6ms | 出口接近上限,重传和 qdisc 丢弃增加 | 应用执行时间变化小 | 网络出口、队列或路径拥塞 |
| 场景 B | 180ms → 900ms | 单核接近 100%,r 队列增加 | 稳定 | await 5ms | 流量低于上限,无丢包 | 工作线程忙碌度升高 | CPU、单线程或锁竞争 |
| 场景 C | 180ms → 1.5s | 45%,无明显 steal | 稳定 | 本机 I/O 正常 | RTT 和重传正常 | 连接池等待、数据库锁等待增加 | 应用连接池或数据库 |
| 场景 D | 180ms → 1.1s | %iowait 升高 | swap in/out 增加 | await 5ms → 80ms,队列变长 | 网络正常 | 请求排队增加 | 内存压力引发 I/O 抖动 |
从表中可以看出,单独看 p95 只能知道“业务变慢”,不能知道原因。单独看网络流量,也不能证明网络拥塞;单独看 CPU 高,更不能排除数据库等待。
可以使用下面的判断顺序:

- 先确认时间是否一致:用户 p95 上升的分钟,服务器指标是否同步变化。
- 再确认指标是否具备因果方向:例如网络队列和重传增加是否早于请求超时。
- 排除替代解释:CPU 低时检查数据库和应用队列,网络异常时检查接口丢弃与 TCP 重传。
- 检查是否只影响单个接口:只有某个接口变慢,通常更像业务逻辑、慢查询或特定响应体问题;所有接口都变慢,才更像系统或网络层问题。
- 至少复测两个窗口:一次变化可能是偶发事件,重复出现才适合作为扩容或配置调整依据。
九、配置相同的服务器,为什么晚高峰差异会被放大
1. 网络路径和出口状态不同
即使两台服务器的 CPU、内存和磁盘参数一致,实际流量仍可能经过不同的上游路径。晚高峰时,某条路径的 RTT、抖动、队列或重传会先发生变化,用户就会感觉服务器变卡。
这类问题的特点通常是:
- 客户端连接或下载耗时增加;
- 服务器业务 TTFB 变化不明显,或仅部分请求受影响;
- TCP 重传、RTT、出口队列或接口丢弃同步增加;
- 服务器 CPU、内存和磁盘没有相同幅度的变化。
2. 虚拟化调度和共享资源不同
配置页面显示相同,不代表同一时刻获得的调度能力完全一致。虚拟机的 %steal、网络队列、宿主机共享设备状态都可能在高峰期产生差异。
如果一台服务器在晚高峰 %steal 明显升高,而另一台没有,即使两者 CPU 使用率相近,也不能认为实际计算能力相同。
3. 应用状态和数据冷热不同
缓存是否命中、连接池是否已经占满、数据库缓存是否预热、某个接口的请求参数是否改变,都会影响晚高峰表现。服务器规格一致,只能排除部分硬件差异,不能排除软件状态和业务数据差异。
因此,比较两台服务器时,必须同时记录:
- 相同接口的请求量和响应体大小;
- 应用版本与配置;
- 数据库连接池和查询等待;
- 缓存命中情况;
- 网络路径和出口变化;
- 每个 CPU 核心而不是只有总 CPU。
十、测试成功与失败后的回滚
1. 成功验证标准
一次有效的瓶颈判断,至少应满足以下条件:
- 成功采集了非高峰和晚高峰的同口径数据;
- 用户侧请求耗时与服务器指标使用同一时间基准;
- 至少有两个相关指标同步变化;
- 已检查并排除明显的替代解释;
- 在另一个晚高峰窗口中出现相近的指标组合;
- 修改参数前后,能够明确比较 p95、错误率和资源余量。
例如,认定网络瓶颈前,最好同时看到客户端响应下载时间增加、出口或 qdisc 接近上限、TCP 重传增加,并确认 CPU、内存、磁盘和数据库等待没有同步恶化。
2. 采集过程异常时
如果采样命令本身造成负载、输出过多或影响业务,应立即停止高频采集:
# 在当前终端停止前台采集
Ctrl+C
短时诊断命令通常不会留下持久配置,因此回滚动作就是停止采集并保留已记录的数据。如果通过脚本、定时任务或监控代理增加了持续采集,应删除或停用对应任务,并确认 CPU、磁盘写入和网络流量恢复到原有水平。
不要把采样间隔从 1 秒改成极短间隔,也不要在晚高峰并行执行大量 ping、traceroute 或压力请求。
3. Nginx 临时日志变更异常时
如果增加的日志格式导致 nginx -t 失败,不要 reload:
sudo nginx -t
若已经应用但发现磁盘写入明显增加、日志格式错误或业务异常,应恢复变更前的配置备份:
sudo cp -a /etc/nginx/nginx.conf.bak-YYYY-MM-DD-HHMMSS \
/etc/nginx/nginx.conf
sudo nginx -t
sudo systemctl reload nginx
实际备份文件名应替换为执行变更时生成的文件。若日志配置位于独立 include 文件,应恢复那个 include 文件,而不是覆盖整个主配置。恢复后检查访问日志和业务请求,确认 Nginx 进程、状态码和响应耗时回到正常范围。
4. 资源参数调整后的回滚原则
如果后续根据证据调整了线程数、连接池、缓存或内存参数,必须保留:
- 修改前的配置文件;
- 修改时间;
- 修改项和原值;
- 变更前后的 p95、错误率、CPU、内存、磁盘和数据库指标。
一次只改一个主要变量。若 p95、错误率、队列或数据库等待恶化,应恢复原值并重新加载相应服务配置,而不是继续叠加其他调整。没有确认具体服务和发行版时,不要直接复制带有 sysctl、防火墙或数据库写操作的命令。
下一次晚高峰应同时观察的指标组合
下一轮排查不要只收集一张 CPU 图。建议固定记录以下组合,并使用同一个时间轴:
- 网络链路:客户端 connect、TTFB、total,ping RTT/丢包,traceroute 终点表现,接口吞吐,RX/TX dropped,qdisc dropped,TCP retrans;
- CPU 调度:每核使用率、
r队列、%iowait、虚拟机%steal; - 内存状态:available、swap in/out、memory PSI、OOM 记录;
- 磁盘 I/O:await、队列、util、读写吞吐、文件系统空间和 inode;
- 应用状态:请求量、p95/p99、错误率、线程忙碌度、请求队列;
- 数据库状态:活跃连接、连接池等待、慢查询、锁等待和数据库 I/O。
当这些指标按时间关联起来,才能回答“配置一致的美国服务器为何晚高峰更卡”:如果网络指标先恶化而资源指标平稳,优先查网络路径、出口和队列;如果 CPU 调度或 %steal 先恶化,优先查计算资源;如果内存压力带动磁盘等待,优先处理内存与缓存;如果应用或数据库队列先增长,则应从线程池、连接池、锁和查询执行路径入手。这样形成的判断,比依据单个 ping、单个 CPU 百分比或一次重启后的短暂恢复更可靠。