第二章 测试环境搭建:硬件选型、软件栈配置与网络拓扑
搭建一个靠谱的压力测试环境,其实比写测试脚本更考验功底。我见过太多团队,脚本写得花里胡哨,结果环境本身就有硬伤——测出来的数据根本没法看。今天咱们就把这块掰开揉碎了讲。
2.1 硬件选型:CPU、内存与网络
硬件选型这事儿,说白了就是「别让短板卡死你」。交易系统对延迟极其敏感,你想想看,一个订单从客户端发出到交易所确认,中间经过多少跳?每一跳都是成本。
2.1.1 CPU:核心频率 vs 核心数量
我个人习惯,交易系统的压测节点优先选高主频CPU。为什么?因为交易处理大多是串行逻辑,高频能直接压降单笔延迟。我在项目中遇到过,用E5-2680 v4(14核2.4GHz)压测,结果发现CPU根本跑不满,但延迟就是下不来。后来换成i9-10900K(10核5.3GHz),延迟直接砍半。
| 场景 | 推荐CPU | 核心数 | 主频 |
|---|---|---|---|
| 高频交易压测 | Intel i9 / AMD Ryzen 9 | 8-16 | ≥4.5GHz |
| 并发连接压测 | Intel Xeon / AMD EPYC | 32-64 | ≥2.8GHz |
| 网关/路由节点 | Intel Xeon D | 4-8 | ≥2.2GHz |
2.1.2 内存:够用就好,但别省
内存这块其实没那么玄乎。交易系统的压测,内存主要用来缓存订单簿、持仓数据、以及一些中间结果。我一般按「峰值订单数 × 单笔订单内存占用 × 2」来估算。
举个例子:假设峰值每秒10万笔订单,单笔订单在内存里占2KB,那每秒就需要200MB。考虑到GC和系统开销,我建议至少配64GB。嗯,这里要注意,内存频率也很重要——DDR4-3200和DDR4-2400,在极端压测下延迟能差出5-8微秒。
2.1.3 网络:万兆起步,25G不嫌多
网络是交易系统的命脉。我曾经吃过一次大亏——用千兆网卡做压测,结果发现网络成了瓶颈,CPU和内存都闲着。后来换成万兆网卡,吞吐量直接翻了8倍。
我的建议:
- 压测节点到被测系统:至少万兆(10GbE),有条件上25GbE
- 网卡型号:Intel X710 / Mellanox ConnectX-5 以上
- 网卡调优:开启RSS(接收端缩放)、关闭LRO/GRO
2.2 软件栈配置:OS参数调优与JVM调优
硬件选好了,软件配置跟不上也是白搭。这部分我踩过的坑最多,咱们一个一个说。
2.2.1 OS参数调优(Linux)
Linux内核默认配置是为通用场景设计的,交易系统压测需要做大量调整。我整理了一份清单,每次搭建环境都会跑一遍:
# 网络参数
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728
net.core.netdev_max_backlog = 50000
net.ipv4.tcp_max_syn_backlog = 50000
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_tw_reuse = 1
# 内存参数
vm.swappiness = 1
vm.dirty_ratio = 10
vm.dirty_background_ratio = 5
# 调度器
kernel.sched_min_granularity_ns = 10000000
kernel.sched_wakeup_granularity_ns = 15000000
为什么这么调?说白了就是让系统更「实时」——减少缓存、减少合并、减少等待。我习惯把swappiness设成1,尽量少用swap,因为swap一触发,延迟直接崩。
2.2.2 JVM调优
如果被测系统是Java写的(大部分交易系统都是),JVM调优就是重中之重。我见过最夸张的情况,GC暂停时间占了总运行时间的30%。
我的JVM参数模板:
-Xms8g -Xmx8g
-XX:+UseG1GC
-XX:MaxGCPauseMillis=10
-XX:G1HeapRegionSize=4m
-XX:+ParallelRefProcEnabled
-XX:-UseBiasedLocking
-XX:+AlwaysPreTouch
-XX:+UseStringDeduplication
-XX:+UnlockExperimentalVMOptions
-XX:G1NewSizePercent=30
-XX:G1MaxNewSizePercent=40
这里重点说几个:
- AlwaysPreTouch:启动时就把内存全部分配好,避免运行时缺页中断。代价是启动慢一点,但压测时值得。
- UseBiasedLocking:关闭偏向锁。交易系统里锁竞争激烈,偏向锁反而增加开销。
- MaxGCPauseMillis=10:目标GC暂停不超过10ms。实际能不能做到,还得看你的对象分配速率。
2.3 网络拓扑与延迟模拟
网络拓扑这块,我建议画一张图,把每个节点的物理位置、网络跳数、延迟预算都标清楚。咱们先看一张我常用的拓扑图:
这张图里,我特意加了一个「网络延迟模拟器」。为什么?因为真实交易场景中,客户端到交易所的物理距离决定了基础延迟。比如从上海到深圳,光纤来回大概10ms。你压测时如果不模拟这个延迟,测出来的数据就太「理想」了。
2.3.1 延迟模拟工具
Linux下最常用的是tc netem。我一般这么用:
# 模拟10ms延迟,±2ms抖动,0.1%丢包
tc qdisc add dev eth0 root netem delay 10ms 2ms distribution normal loss 0.1%
# 查看当前配置
tc qdisc show dev eth0
# 清除配置
tc qdisc del dev eth0 root
这里有个坑——netem的延迟是加在系统协议栈里的,如果你用DPDK或者RDMA,它就不生效了。我遇到过这种情况,后来改用硬件延迟模拟器才搞定。
2.3.2 网络拓扑设计原则
我总结了几条原则,供你参考:
- 物理隔离:压测网络和生产网络必须物理隔离。我曾经见过有人用VLAN隔离,结果压测流量广播到了生产环境,差点酿成事故。
- 对称拓扑:压测客户端和被压系统之间的网络路径尽量对称。不对称的拓扑会导致延迟分布不均匀,数据不好分析。
- 旁路监控:监控节点不要串在数据路径上,用镜像端口或者旁路采集。串进去会引入额外延迟。
好了,环境搭好之后,下一步就是写压测脚本了。不过那是下一章的内容,咱们先把基础打牢。记住一句话:环境搭不好,后面全白搞。