3. 压测环境搭建:硬件选型与系统调优
做延迟压测,最怕什么?
怕你测了半天,发现瓶颈不在代码,而在网卡。怕你调优三天,结果操作系统参数没改,白忙活一场。我见过太多团队,上来就写压测脚本,结果环境没搭好,数据全废了。
这一章,咱们把地基打牢。
3.1 硬件选型:CPU、内存、网卡
硬件选型,说白了就是三个字:别省钱。但也不是无脑堆配置,得对症下药。
3.1.1 CPU:核心频率比核心数更重要
交易数据总线,处理的是高频小报文。延迟敏感,吞吐量反而不是第一优先级。
- 高主频优先:我个人习惯选 3.5GHz 以上的 CPU。核心数 8-16 核足够,太多核反而可能引入 NUMA 延迟。
- 关闭超线程:超线程对延迟类应用不友好。我在项目中遇到过,开了超线程后,P99 延迟直接翻倍。嗯,后来就再也没开过。
- 选择 Intel 还是 AMD?:目前来看,Intel 的 Xeon 系列在低延迟场景下依然有优势。AMD 的 EPYC 性价比高,但某些微架构的缓存延迟略高。
我的经验: 压测机建议用 Intel Xeon Gold 或 Platinum 系列。别用消费级 CPU,虽然便宜,但 PCIe 通道数和内存通道数都受限,容易成为瓶颈。
3.1.2 内存:容量够用,频率要快
内存这块,很多人容易忽略频率。
- 容量:32GB 起步,64GB 更稳妥。压测时,操作系统会缓存大量网络数据包,内存不够会触发 swap,延迟瞬间飙升。
- 频率:DDR4 3200MHz 或更高。内存频率直接影响内存访问延迟,进而影响数据总线的处理速度。
- 通道数:尽量插满内存通道。比如双路服务器,每个 CPU 插满 6 根内存条,发挥最大带宽。
注意: 别用 ECC 内存?不,交易系统必须用 ECC。数据完整性比那一点点延迟更重要。我曾经因为内存比特翻转,查了三天 bug,最后发现是内存条坏了。
3.1.3 网卡:延迟的命门
网卡是延迟压测的核心。你想想看,数据从网线进来,经过网卡、驱动、内核协议栈,每一步都在消耗时间。
- 25Gbps 起步:现在 10G 网卡已经不够看了。25G 是主流,100G 更好。但要注意,网卡带宽要和 CPU 处理能力匹配。
- 支持 DPDK 或 RDMA:如果要做极致延迟,必须用 DPDK 或 RDMA。传统内核协议栈的延迟在 10-50 微秒级别,DPDK 可以降到 1 微秒以下。
- 网卡型号推荐:Mellanox ConnectX-5/6 系列,或者 Intel E810 系列。这两个我都用过,稳定性不错。
核心原则: 网卡延迟 + 驱动延迟 + 内核延迟,三者之和要小于你的目标延迟。比如目标延迟 10 微秒,那网卡本身延迟不能超过 2 微秒。
3.2 操作系统调优:内核参数与文件描述符
硬件选好了,系统不调优,等于白搭。我见过有人买了最好的硬件,结果跑压测时,系统参数还是默认的,延迟惨不忍睹。
3.2.1 内核参数调优
以下是我常用的内核参数调整,直接贴出来,你可以照着改。
# 网络相关
net.core.rmem_max = 134217728 # 接收缓冲区最大 128MB
net.core.wmem_max = 134217728 # 发送缓冲区最大 128MB
net.core.rmem_default = 16777216 # 接收缓冲区默认 16MB
net.core.wmem_default = 16777216 # 发送缓冲区默认 16MB
net.core.netdev_max_backlog = 500000 # 网卡队列最大 backlog
net.core.somaxconn = 65535 # 最大连接数
# TCP 优化
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728
net.ipv4.tcp_congestion_control = bbr # BBR 拥塞控制算法
net.ipv4.tcp_fastopen = 3 # 开启 TCP Fast Open
net.ipv4.tcp_slow_start_after_idle = 0 # 关闭空闲后慢启动
# 中断处理
kernel.sched_migration_cost_ns = 5000000 # 减少进程迁移
kernel.sched_autogroup_enabled = 0 # 关闭自动分组
# 内存管理
vm.swappiness = 1 # 尽量少用 swap
vm.dirty_ratio = 10 # 脏页比例
vm.dirty_background_ratio = 5
避坑指南: 我曾经在压测时发现延迟忽高忽低,查了半天,发现是
tcp_slow_start_after_idle 没关。连接空闲几秒后,TCP 重新慢启动,延迟直接飙到 100 毫秒。嗯,从那以后,这个参数我必改。
3.2.2 文件描述符
压测时,系统会打开大量 socket 连接。默认的 1024 个文件描述符,根本不够用。
# 临时修改
ulimit -n 1048576
# 永久修改(/etc/security/limits.conf)
* soft nofile 1048576
* hard nofile 1048576
root soft nofile 1048576
root hard nofile 1048576
# 系统级限制(/etc/sysctl.conf)
fs.file-max = 2097152
为什么是 1048576?说白了,就是 2^20。这个数字够大,又不会浪费内存。我一般压测时,每个连接消耗约 4KB 内存,100 万个连接大约 4GB,可以接受。
3.3 网络拓扑设计
网络拓扑,决定了你的压测数据怎么走。设计不好,延迟数据全是假的。
3.3.1 拓扑原则
- 直连优先:压测机和被测系统之间,尽量用网线直连。不要经过交换机,交换机引入的延迟在 1-5 微秒,虽然不大,但会干扰你的判断。
- 同机房部署:如果必须经过交换机,确保压测机和被测系统在同一个机柜内。跨机柜的延迟差异可能达到 10 微秒以上。
- 独立网段:压测流量和生产流量隔离。别把压测流量混到生产网络里,否则两边都受影响。
3.3.2 典型拓扑结构
下面这张图,是我常用的压测拓扑。你一看就明白。
3.3.3 拓扑设计要点
- 压测机与被测系统直连:这是最干净的拓扑。延迟数据不受网络设备干扰。
- 监控机旁路接入:监控机通过端口镜像或分光器接入,不影响主链路。我习惯用 tcpdump 抓包,然后离线分析延迟。
- 交换机备选方案:如果必须经过交换机,选低延迟交换机。比如 Mellanox SN2700,延迟在 1 微秒以内。
注意: 别把监控机串在主链路上。我曾经见过有人把监控机当网关用,结果监控机网卡故障,压测直接中断。监控机必须旁路,不能成为单点故障。
3.4 环境验证清单
环境搭好后,别急着跑压测。先做一轮验证,确保环境没问题。
| 检查项 | 预期值 | 验证方法 |
|---|---|---|
| CPU 频率 | ≥ 3.5GHz | lscpu | grep MHz |
| 内存带宽 | ≥ 40GB/s | mbw -n 10 1024 |
| 网卡延迟 | ≤ 2μs | ping -c 100 -i 0.001 |
| 文件描述符 | ≥ 1048576 | ulimit -n |
| 内核参数 | 与配置一致 | sysctl -a | grep net.core |
| 网络连通性 | 延迟稳定 | mtr -n 目标IP |
我的习惯: 每次压测前,先跑一轮
ping 和 iperf,确认网络延迟和带宽正常。如果 ping 延迟超过 10 微秒,说明网络有问题,先排查再压测。
环境搭好了,硬件选对了,系统调优了,拓扑设计合理了。接下来,就可以开始真正的压测了。记住,环境是压测的基石,地基不稳,楼盖得再高也是危楼。