VPN 吞吐量低是熵问题吗?通常不是
启动时等待随机数的卡顿和缓慢的隧道是两种不同的故障。在改动种子或缓冲区之前,先测量你遇到的是哪一种。
穿过隧道的低吞吐量和因等待随机数而卡住的机器带来截然不同的体验,却被归入同一种抱怨。前者表现为什么都还无法工作之前的停顿。后者表现为连接可用、但在你观察的整个过程中都缓慢传输数据。判断你遇到的是哪一种只需十分钟,却能省下一周的猜测。
两种看起来相似的症状
全新启动后、在尚未接受任何连接之前就挂起的服务,是在等待某样东西。快速建立、随后只以预期速度的一小部分传输的隧道,则受制于别的东西。两段叙述里都出现了加密这个词,因此它们被混为一谈。在改动配置文件之前,先把它们区分开。
在启动、认证、密钥重新协商和传输本身周围打上时间戳。隧道可用之前的长延迟并不是低而稳定的速率,把两者平均成一个数字会毁掉证据。
systemd-analyze blame | head -10 journalctl -u [email protected] -o short-precise | head -40 cat /proc/sys/kernel/random/entropy_avail
前两条命令把启动工作放到时间轴上。第三条打印内核的熵记账值,它作为单个数据点有用,作为带宽计则毫无用处。
等待随机数实际上是什么样子
对安全随机字节的请求可能会阻塞,直到内核初始化它的随机源。这一点在虚拟机和小型嵌入式板卡上、启动早期收集到的环境噪声很少时最为重要。但由此并不能推出每个加密字节都消耗新的熵。
现代生成器只播种一次,随后由确定性构造产生输出,并按自己的日程重新播种。批量传输并不会逐字节抽干熵池,所以缓慢传输期间的低池值说明不了任何关于原因的事。
strace -f -e trace=getrandom -p $(pidof openvpn) 2>&1 | head -20 dmesg | grep -i 'random\|crng'
第一条命令显示进程在你观察时是否正停留在随机数调用中。第二条显示内核自身的初始化消息,早期启动的卡顿正是在那里变得可见。
记录内核版本以及服务实际链接的库,因为不同实现和不同版本的行为并不相同。恢复之后抓取的跟踪通常会完全错过那次停顿。
持续性的缓慢实际上是什么样子
全程都传输得很慢的隧道受制于数据路径。单个线程饱和、外层丢包、重传或套接字队列填满,各自都会造成那种迹象,也各有各的修法。聚合的 CPU 百分比会掩盖单个忙碌线程,这是最常见的误读。在看总体负载之前,先看每线程的耗时。
用可比的基线双向测量,并观察接口计数器,而不是应用程序自己的报告。
ss -tin dst 203.0.113.10 nstat -az | grep -i 'drop\|retrans' ethtool -S eth0 | grep -i 'drop\|error'
第一条命令显示一个对端的队列与拥塞状态。第二、第三条报告协议栈和接口上的丢弃与重传,原因通常最先在那里出现。
针对你测到的瓶颈选择对应的修法
如果证据指向启动早期的初始化,就去看平台支持的播种路径,在虚拟机上它可能包括由宿主提供的随机设备。把同一份种子镜像原样复制到众多客户机,并不能代替独立的初始化。
如果证据指向数据路径,就调整计数器所指向的东西。缓冲区大小在队列溢出时有帮助,而在线程饱和时毫无作用。装一个熵守护进程把计数器抬高,并不是吞吐量的修复;为了让图表好看而改变播种假设,则是用安全属性换一个数字。
只有当同一测量在同样条件下变好时,才接受这项改动。更大的计数器不是结果;测得的最短等待,或原因明确的更快传输,才是结果。