先判断你撞上的是三种瓶颈中的哪一种,再去买更大的实例。一个核心满载、其余空闲,说明是每个连接的加密工作。传输时所有核心都饱和,说明是总处理能力。CPU 不高而重传数在涨,说明问题在网络路径。三者的第一步完全不同,只有一种能靠更大的实例解决。

三种瓶颈,一张表,三种修法

LimitReading during a transferFirst move
Single threadone core near 100%, siblings idlespread flows across workers
Aggregate CPUevery core busy, load average climbscapacity, or less work per byte
Path or providerlow CPU, retransmits or steal time highMTU, loss, host contention

把表格的每一行当作诊断,而不是阶段。一个线程跑满 100%、其余线程空闲,是单个大隧道网关上最常见的结果,因为这条流的加密只在一个核心上跑。传输期间所有核心都忙,说明机器已经尽了全力。CPU 不高而重传持续上升,说明处理器在等一个不断丢包的链路。

按证据顺序修。把流量分散到多个工作线程,只对第一种情况有效,对第二种毫无作用。更大的实例能解决第二种,却在第一种上白花钱。调整 MTU 或处理丢包,是唯一能碰到第三种情况的做法。 在还不知道自己在哪一行时就买容量 是最贵的猜测方式。

把吃紧的线程和忙碌的主机分开看

先从每核利用率入手,避免某个被卡住的核对平均值隐身。传输过程中跑一次,能看出负载是平的还是带尖峰的。两种形态都有信息量,而带尖峰往往说明采样窗口抓到的是调度器活动,而不是加密本身。

mpstat -P ALL 1 5

先把忙的核心归到某个进程,再归到某个线程。下面这条命令会把父线程和子线程一起保留,这在守护进程按连接 fork 时很关键:

pidstat -u -t -p $(pgrep -f 'openvpn|wireguard|ipsec') 1 10

内核里的加密永远不会出现在用户态进程计数器里。单独采样线程,再把这个视角和进程的账目对照:

top -H -b -n 1 | head -20

套接字计数器放在最后看,因为它决定加 CPU 到底有没有用。CPU 平稳而重传上升,不是处理器的问题。采样时让传输保持运行,否则这些数字描述的是一台空机器:

ss -ti | grep -E 'retrans|cwnd|rtt'

做一次受控传输,并且跑两遍

空闲计数器什么都证明不了,拿随机对端做基准测试也几乎证明不了什么。选一个客户端、一个目标、一次有代表性的传输,然后在同一时间窗口里记录吞吐和交互延迟。网关可能已经饱和,而大文件拷贝仍能跑完;真正让用户有感觉的是延迟曲线。把这次传输、客户端数量和守护进程版本写在数字旁边。

用多条并行流重复一次。增加流数后吞吐上升,说明瓶颈在每流的窗口;只有一个核心卡住而吞吐不变,说明瓶颈在处理。

然后把可选的负载停掉,再跑一次。同一台主机上的备份、日志转发或数据库,会让平均值看起来很忙,却和隧道毫无关系。如果主机其他方面都很安静、CPU 依旧被卡住,证据就指向 VPN 进程。如果 CPU 下来了,说明你一直在测邻居,网关根本不是问题。

在买硬件之前先排除路径

重传上升、拥塞窗口缩小、往返时延变大,这些都在把矛头从处理器上挪开。比较隧道 MTU 和路径 MTU,检查底层链路的丢包,确认客户端自己的上行不是瓶颈。更大的网关修不好一条丢包的链路,而用户会用同样的词描述这两种故障。重传计数器几分钟内就能把它们分开。

在虚拟服务器上,要把服务商的指标和客户机自己的指标放在一起看。被偷走的时间,就是超卖在客户机内部显现的方式,客户机里任何调优都去不掉它。客户机的计数器看不到宿主机,所以客户机图表干净,并不等于宿主机健康。

一次只改一项,只测一次

选择证据支持的那个假设,然后只改一项有文档支持的设置:工作线程数、有文档的卸载选项,或者实例规格。OpenVPN 发布了性能排障指南,讲的是同一套处理与传输的分界: OpenVPN 性能排障。

先确认卸载选项真的生效,而不是相信那个开关,然后用同样的传输复测、做同类比较。这是把真实改善和安静下午区分开的唯一办法。留一个能回滚的检查点,因为第二次改动往往就是人们记不清哪次起作用的时候。每轮只动一个变量,慢的是一天,快的是一个月。

不要为了图表好看去削弱认证或加密套件。如果 CPU 依旧不跟着症状走,就回到路径和应用层检查,而不是凭猜测升级硬件。

相关文章