上一篇 下一篇 分享链接 返回 返回顶部

香港物理服务器性能波动来自哪里?如何用 perf top、vmstat 与 dstat 联动诊断全流程

发布人:Minchunlin 发布时间:2025-07-31 11:36 阅读量:137


那是一个星期三凌晨 3 点,香港机房的物理服务器突然连续三次触发了 CPU Load 超标的 Zabbix 告警。我迷迷糊糊打开电脑 SSH 进去一台问题机器,第一眼看到的是 top 命令下 load average 飙到 30+,可用户请求并不高。问题显然不是业务层面直接导致的。这是一台跑着高并发 C++ 网关程序的裸金属服务器,性能一向稳定,但这次异常波动明显有系统底层原因。

这篇文章记录了我如何通过 perf top、vmstat 与 dstat 三个工具协同使用,定位出隐藏的性能瓶颈,并最终落地优化方案。这不是 textbook 教程,而是我在一线摸索出来的实战流程。

一、问题初现:负载异常但无明显业务压力

SSH 进入机器,首先是用常规工具做初步观察:

top -n 1

结果如下:

load average: 30.12, 28.33, 25.87
%Cpu(s):  8.0 us, 5.2 sy, 0.0 ni, 85.6 id, 1.2 wa, 0.0 hi, 0.0 si, 0.0 st

尽管系统有 32 核,但 85% CPU 空闲,看起来并不拥堵,为什么 load average 会飙高?是等待 IO 吗?内核调度拥塞?这些只能靠更细粒度的工具来分析。

二、vmstat:调度压力与IO等待的侧写工具

我下一步运行了 vmstat 观察调度行为和 IO 状态:

vmstat 1 10

输出结果中如下字段引起我注意:

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free  buff  cache   si   so    bi    bo   in   cs us sy id wa st
 8  1      0  40000  1234 987654    0    0     2     1  1200  3400 10  5 83  2  0

r 值持续在 8~10 之间,说明有大量进程在等待 CPU(Run queue)

b 值出现了非零,说明有进程处于阻塞状态(可能是磁盘 IO)

wa(I/O wait)也有 2%~3%

这些提示我:虽然 CPU 看起来空闲,但调度队列积压严重,可能存在 kernel-level 竞争或某些系统调用长时间阻塞。

三、dstat:多维资源的时间轴画像

我随后跑了 dstat 来捕捉更多维度的数据,包括磁盘、网络、IO 等:

dstat -cdnm --top-cpu --top-io --top-bio --top-latency

几秒后我注意到:

  • top-io 中有一个 rsyslogd 进程持续出现在榜单上,正在频繁写入日志
  • top-cpu 有一个我们自研的 gatewayd 程序 CPU 使用偶尔飙高
  • 磁盘 util% 偶尔达到 70% 以上

这进一步表明问题并非出在用户业务流量,而是系统服务或内核函数的行为。

四、perf top:内核火焰图之实时入口

接着我使用 perf top 来进一步深挖内核函数的热点调用路径:

sudo perf top -g

在 10 秒的分析中,我看到如下函数频繁出现:

  25.43%  [kernel]  [k] native_queued_spin_lock_slowpath
  18.22%  [kernel]  [k] __do_softirq
  12.50%  [kernel]  [k] _raw_spin_lock_irqsave
   8.14%  [kernel]  [k] schedule

看到这些 spinlock 和 softirq 函数,我基本断定:当前服务器出现了 内核级别锁争用,并且大概率是由于多个核在争抢某个共享资源,比如日志、网络 buffer、驱动层缓冲区等。

五、逐步排查与验证

1. syslog 写入争用

通过 lsof | grep /var/log 发现 rsyslogd 正在大量写入 /var/log/messages 和 /var/log/secure,而我们的服务同时在 syslog 中打印高频日志。

解决措施:

  • 修改 rsyslog.conf 限制频率(加入 :msg, contains, "XXX" ~ 来丢弃部分 DEBUG 级别日志)
  • 改为将部分日志写入独立文件,避免系统日志频繁 flush

2. gatewayd 程序调度抖动

用 perf record -p <pid> 对网关服务采样 30 秒后生成分析报告:

perf report

结果显示:

  • epoll_wait 处于高占比(说明程序常常在等待)
  • 但内部某些 C++ 函数,如 std::map::find 出现在热点中,且调用栈很深

我们优化了这部分代码逻辑,将频繁访问的结构由 std::map 替换为 std::unordered_map,降低查找延迟,减少锁粒度。

六、最终方案与效果

经过多轮调试,我们的方案包括:

  • 降低系统日志写入频率,避免 rsyslogd 导致的 IO 抢占
  • 调整网关程序日志策略,限制无效 DEBUG 输出
  • 优化 C++ 服务的数据结构,降低锁冲突

设置 isolcpus 参数,将中断和内核线程绑定到特定核心,释放更多核心用于用户态程序

并配合如下内核参数调优:

echo 1 > /proc/sys/kernel/sched_schedstats
echo never > /sys/kernel/mm/transparent_hugepage/enabled

优化后,load average 稳定下降至 2~3,rsyslog 不再频繁触发 IO,gatewayd 的延迟下降了 20%,再未发生告警。

七、perf 与 vmstat/dstat 联动的威力

这次香港物理服务器的性能波动是典型的“表面平静、内核涌动”型问题,使用 perf top、vmstat 与 dstat 三者协同诊断非常高效:

  • vmstat 是宏观调度瓶颈的信号灯
  • dstat 提供了 IO 与 CPU 多维动态趋势
  • perf 则是进入内核深水区的望远镜

三者结合,既有高空鸟瞰,又有微观手术刀,才能真正定位并解决物理机复杂的性能瓶颈。

如果你也遇到 load 高但 CPU 占用不高的“鬼影性能问题”,不妨试试这套组合技。别迷信单一工具,工具联动,才是系统优化的正道。

目录结构
全文