2. 测试环境搭建:硬件选型与软件栈配置

环境搭建这事儿,说简单也简单,说复杂能让你折腾一礼拜。我见过太多团队,工具选得挺牛,脚本写得也挺花,结果一跑压测,瓶颈全在环境本身——说白了,你连个靠谱的“试验台”都没搭好,测出来的数据谁敢信?

这一章,我就把硬件选型、软件栈配置、压测工具选型这三块掰开揉碎讲清楚。你跟着我的思路走一遍,至少能少踩一半的坑。

2.1 硬件选型:别让机器拖了后腿

硬件选型有个核心原则:压测机的性能必须远高于被测系统。否则你测出来的不是系统瓶颈,而是压测机自己在喘。

2.1.1 CPU:核心数与频率的博弈

我个人习惯,压测机CPU至少8核起步,16核是标配。为什么?因为并发线程数通常要压到目标系统的2~3倍,核数不够,线程切换开销就能把CPU吃满。

场景 推荐CPU配置 说明
轻量接口压测(< 1000 QPS) 4核8线程 单机JMeter即可
中等规模(1000~10000 QPS) 8核16线程 建议分布式压测
高并发(> 10000 QPS) 16核32线程及以上 必须分布式,注意网络瓶颈
一个小技巧: 选CPU时别只看主频。我踩过坑——某次用高频低核CPU压测,结果线程一多,上下文切换直接把CPU干到100%,吞吐量反而上不去。后来换了低频多核,问题迎刃而解。

2.1.2 内存:够用就好,但别省

内存这块,我的经验是:压测机内存 = 被测系统内存 × 1.5。为什么?因为压测工具本身要缓存响应数据、聚合结果,再加上操作系统开销,少了容易触发Swap。

  • JMeter:每个线程约占用1~2MB堆内存,1000线程就是1~2GB,加上GUI本身,建议至少8GB。
  • Locust:Python进程内存占用相对低,但协程模式下每个用户约几百KB,建议4GB起步。
  • Gatling:基于Akka,内存管理比较高效,但建议也留6GB以上。
注意: 千万别在压测机上跑被测系统的数据库或中间件!我曾经见过有人图省事,把MySQL和JMeter装在同一台机器上,结果压到一半,数据库OOM,整个环境崩了。压测机和被测系统必须物理隔离。

2.1.3 磁盘:IOPS才是关键

磁盘选型,很多人只看容量,其实压测场景下IOPS(每秒读写次数)才是关键指标。尤其是做日志记录、结果持久化时,磁盘IO很容易成为瓶颈。

磁盘类型 典型IOPS 适用场景
机械硬盘(HDD) 100~200 不推荐,除非只做极低并发
SATA SSD 5000~10000 中等规模压测,够用
NVMe SSD 50000~100000 高并发压测,首选

我个人习惯,压测机至少配一块NVMe SSD做系统盘和数据盘。如果条件有限,SATA SSD也能凑合,但千万别用HDD——你想想看,压测结果写到一半,磁盘队列深度飙到100+,那画面太美我不敢看。

2.1.4 网络:千兆是底线,万兆不嫌多

网络这块,我吃过不少亏。有一次压测一个API网关,本地压测机千兆网卡,被测服务器也是千兆,结果死活压不到目标QPS。后来一查,网卡跑满了,丢包率飙升。换了万兆网卡,问题直接解决。

选型建议:

  • 千兆网卡:适合单机压测,QPS在5000以下。
  • 万兆网卡:分布式压测或QPS超过5000时,必须上。
  • 网线/交换机:别用劣质网线,至少超五类,最好六类。交换机端口不要共享带宽。
核心原则: 压测环境的网络带宽,至少是被测系统生产环境带宽的2倍。否则网络本身就成了瓶颈,你测出来的数据毫无意义。

2.2 软件栈配置:OS、中间件与数据库

硬件选好了,软件配置也不能马虎。我见过太多人,硬件挺牛,结果操作系统参数没调,中间件配置没优化,压测一跑就崩。

2.2.1 操作系统调优

Linux是压测首选,Windows在并发场景下表现一般。我习惯用CentOS 7或Ubuntu 20.04 LTS,稳定且社区支持好。

关键参数调整:

# 文件描述符限制(默认1024,压测必须调大)
ulimit -n 65535

# 网络参数优化
sysctl -w net.core.somaxconn=65535
sysctl -w net.ipv4.tcp_max_syn_backlog=65535
sysctl -w net.ipv4.tcp_tw_reuse=1
sysctl -w net.ipv4.tcp_fin_timeout=30

# 内存参数
sysctl -w vm.swappiness=10
sysctl -w vm.dirty_ratio=30
sysctl -w vm.dirty_background_ratio=5
避坑指南: 我曾经在压测前忘了调ulimit -n,结果JMeter跑到一半报Too many open files,整个压测白跑。现在我把这些参数写成了脚本,每次压测前自动执行。

2.2.2 中间件配置

中间件这块,我重点说Nginx和Tomcat,这两个是压测中最常见的。

中间件 关键参数 推荐值 说明
Nginx worker_processes CPU核心数 充分利用多核
Nginx worker_connections 65535 最大并发连接数
Tomcat maxThreads 200~500 根据CPU和内存调整
Tomcat acceptCount 100 等待队列长度

嗯,这里要注意:中间件的参数不是越大越好。比如Tomcat的maxThreads设成2000,CPU扛不住,反而会频繁上下文切换,吞吐量下降。我一般先设一个保守值,压测时观察CPU和线程数,再逐步调优。

2.2.3 数据库配置

数据库是压测中的重灾区。我见过最离谱的一次,压测时MySQL的max_connections没调,默认151,结果压到200并发直接报错。

MySQL关键参数:

# 连接数
max_connections = 500
# 缓冲池(设为物理内存的70%)
innodb_buffer_pool_size = 8G
# 日志文件大小
innodb_log_file_size = 1G
# 查询缓存(高并发下建议关闭)
query_cache_type = 0
query_cache_size = 0
注意: 压测前一定要检查数据库的慢查询日志和连接池配置。我曾经遇到过,压测时数据库连接池耗尽,应用层报错,但数据库本身CPU才20%——典型的连接池配置问题,不是数据库性能问题。

2.3 压测工具选型:JMeter、Locust、Gatling

工具选型这事儿,没有绝对的好坏,只有合不合适。我三个工具都用过,说说我的感受。

2.3.1 JMeter:老牌劲旅,生态最全

JMeter是我用得最多的工具。优点很明显:

  • 插件丰富:从HTTP到JDBC到MQ,几乎什么协议都能测。
  • GUI友好:录制脚本、调试参数都很方便。
  • 分布式支持:一台Master控制多台Slave,适合大规模压测。

缺点也有:

  • 内存消耗大:GUI模式下尤其明显,我一般用命令行模式跑。
  • 脚本维护麻烦:JMX文件是XML格式,版本控制不太友好。

2.3.2 Locust:Python党的最爱

Locust用Python写脚本,代码即配置。我比较喜欢它的协程模式,单机并发能力比JMeter强。

# 一个简单的Locust脚本
from locust import HttpUser, task, between

class WebsiteUser(HttpUser):
    wait_time = between(1, 5)
    
    @task
    def index_page(self):
        self.client.get("/")
    
    @task(3)
    def view_item(self):
        self.client.get("/item?id=1")

优点:

  • 代码可维护:Git管理方便,支持CI/CD集成。
  • Web UI实时监控:跑的时候能看到实时QPS和响应时间。

缺点:

  • 协议支持有限:主要支持HTTP,其他协议需要自己写。
  • 分布式配置稍复杂:需要启动多个Worker进程。

2.3.3 Gatling:Scala加持,性能怪兽

Gatling基于Akka和Netty,性能是三个工具里最好的。我一般用它做高并发压测。

// 一个简单的Gatling脚本
class BasicSimulation extends Simulation {
  val httpProtocol = http.baseUrl("http://localhost:8080")
  
  val scn = scenario("BasicSimulation")
    .exec(http("request_1").get("/"))
    .pause(5)
  
  setUp(
    scn.inject(atOnceUsers(100))
  ).protocols(httpProtocol)
}

优点:

  • 性能极高:单机可模拟数万并发。
  • 报告精美:HTML报告自带图表,分析方便。

缺点:

  • 学习曲线陡:需要懂Scala或Java。
  • 调试不方便:编译型语言,改脚本要重新编译。

2.3.4 选型对比

维度 JMeter Locust Gatling
学习成本 低(GUI操作) 中(Python基础) 高(Scala/Java)
单机并发能力 中(5000~10000) 高(10000~30000) 极高(30000+)
协议支持 丰富(插件生态) 有限(HTTP为主) 中等(HTTP/WebSocket)
报告质量 中(需插件增强) 中(Web UI实时) 高(HTML静态报告)
CI/CD集成 中(命令行模式) 高(Python脚本) 高(Maven/Gradle)

我个人建议:团队有Python基础,选Locust;追求极致性能,选Gatling;通用场景,选JMeter。没有最好的工具,只有最适合你场景的工具。

2.4 环境搭建知识体系总览

说了这么多,我画了一张图,把环境搭建的核心逻辑串起来。你一看就明白:

测试环境搭建知识体系 测试环境搭建知识体系 硬件选型 软件栈配置 压测工具选型 CPU(8核+) 内存(16GB+) 磁盘(NVMe) 网络(万兆) OS调优 中间件配置 数据库调优 连接池配置 JMeter Locust Gatling 分布式压测 核心原则:压测环境必须与被测系统物理隔离 硬件性能至少是被测系统的2倍,避免压测机成为瓶颈

这张图把环境搭建的三大模块和关键节点都串起来了。你搭建环境时,就按这个框架走:先搞定硬件,再调软件栈,最后选工具。每一步都有坑,但只要你按我说的来,至少能保证环境本身不出问题。

最后说一句: 环境搭建不是一次性工作。每次压测前,我习惯花10分钟检查一下硬件资源、网络延迟、系统参数——别嫌麻烦,这10分钟能帮你省下后面几小时的排障时间。