三、压测环境搭建:单机、分布式与容器化
说到压测环境搭建,我见过太多团队在这上面栽跟头了。有人用笔记本压线上服务,结果网络延迟先成了瓶颈;有人一上来就搞几十台机器集群,最后发现单机就能搞定。说白了,环境搭建这事,得看你的目标是什么。
我个人习惯把压测环境分成三类:单机、分布式、容器化。每种都有它的适用场景,也有它的坑。今天咱们一个一个聊。
3.1 单机压测环境
单机压测,就是在一台机器上跑压测工具。比如你用 JMeter 或者 wrk,在本机发请求压本机或远程服务。
什么时候用单机?
- 接口数量少,QPS 预期不高(比如几千以内)
- 快速验证功能,比如看看接口通不通、响应时间对不对
- 开发自测阶段,不想折腾复杂环境
我踩过的坑: 有一次我用笔记本压一个本地服务,结果 CPU 被打满了,压测结果惨不忍睹。后来才发现,压测工具和被测服务抢资源了。你想想看,一台机器既要发请求又要处理请求,结果能准吗?
单机压测的典型配置:
# 用 wrk 压测一个 HTTP 接口
wrk -t12 -c400 -d30s http://localhost:8080/api/test
# 参数说明:
# -t12:12 个线程
# -c400:400 个并发连接
# -d30s:持续 30 秒
嗯,这里要注意:并发数不是越大越好。我曾经把并发数调到 2000,结果压测机先挂了,服务端反而没事。所以单机压测的并发上限,一般建议不超过 1000。
3.2 分布式压测环境
当单机压不动了,就得考虑分布式。说白了,就是用多台机器一起发请求,模拟更大的并发量。
什么时候用分布式?
- 目标 QPS 超过单机压测能力(比如上万甚至十万)
- 需要模拟来自不同 IP 的请求(比如测试负载均衡)
- 压测场景复杂,单机内存或 CPU 不够用
分布式压测的架构:
我习惯用 JMeter 的分布式模式。一台 Master 控制多台 Slave,Slave 负责发请求,Master 负责汇总结果。
# 启动 Slave 节点(在每台压测机上执行)
jmeter-server -Dserver.rmi.localport=50000
# 启动 Master 节点(在控制机上执行)
jmeter -n -t test_plan.jmx -R slave1_ip,slave2_ip -l results.jtl
分布式压测的注意事项:
- Slave 机器配置尽量一致,否则结果会有偏差
- Master 不要参与发请求,只做调度和汇总
- 结果文件(.jtl)不要太大,否则分析起来很慢
我记得有一次压测,用了 10 台 Slave,结果 Master 的内存爆了。后来发现是结果聚合时,Master 把所有数据都加载到内存里了。解决办法是:用 InfluxDB + Grafana 实时看结果,不依赖 JMeter 的聚合报告。
3.3 容器化压测环境(Docker Compose)
容器化压测,是我现在最推荐的方式。为什么?因为环境一致、部署快、好扩展。你想想看,用 Docker Compose 一键拉起压测集群,比手动配置 Slave 省心太多了。
什么时候用容器化?
- 团队需要快速搭建和销毁压测环境
- 压测环境需要和 CI/CD 集成
- 需要模拟复杂的微服务架构
一个典型的 Docker Compose 压测环境:
version: '3.8'
services:
# 压测 Master
jmeter-master:
image: justb4/jmeter:5.5
container_name: jmeter-master
volumes:
- ./test_plans:/test_plans
- ./results:/results
command: >
-n -t /test_plans/test_plan.jmx
-R jmeter-slave1,jmeter-slave2
-l /results/result.jtl
depends_on:
- jmeter-slave1
- jmeter-slave2
# 压测 Slave 1
jmeter-slave1:
image: justb4/jmeter:5.5
container_name: jmeter-slave1
command: jmeter-server -Dserver.rmi.localport=50000
ports:
- "50000:50000"
# 压测 Slave 2
jmeter-slave2:
image: justb4/jmeter:5.5
container_name: jmeter-slave2
command: jmeter-server -Dserver.rmi.localport=50000
ports:
- "50001:50000"
# 结果存储和展示
influxdb:
image: influxdb:1.8
container_name: influxdb
environment:
- INFLUXDB_DB=jmeter
grafana:
image: grafana/grafana:latest
container_name: grafana
ports:
- "3000:3000"
depends_on:
- influxdb
depends_on 控制启动顺序。Master 要等 Slave 都启动后再开始压测。我一般会在 Slave 启动后加个健康检查,确保服务真的就绪了。
容器化压测的优势:
- 环境一致:开发、测试、生产用同一套镜像
- 快速扩展:加一个 Slave 就是加一行配置
- 资源隔离:每个容器独立,互不影响
- 易于清理:压测完直接
docker-compose down
我踩过的坑: 有一次用容器化压测,发现结果比物理机差很多。排查了半天,原来是 Docker 的网络模式问题。默认的 bridge 模式有 NAT 转换,增加了延迟。后来改成 host 模式,结果就正常了。
3.4 三种环境的对比
| 维度 | 单机压测 | 分布式压测 | 容器化压测 |
|---|---|---|---|
| 适用场景 | 快速验证、低并发 | 高并发、多 IP 模拟 | CI/CD、微服务、快速部署 |
| 部署复杂度 | 低 | 中 | 中高(需 Docker 基础) |
| 扩展性 | 差 | 中 | 好 |
| 环境一致性 | 差 | 中 | 好 |
| 资源开销 | 低 | 高 | 中 |
| 结果准确性 | 中(受压测机影响) | 高 | 高(需注意网络模式) |
3.5 知识体系图
下面这张图,是我梳理的压测环境搭建的核心逻辑。你可以把它当成一个决策树,看看自己该选哪种方式。
这张图其实挺直观的。你从根节点开始,根据你的场景往下走,就能找到合适的方案。我个人建议:如果团队有 Docker 基础,直接上容器化方案。省心、好维护,而且容易集成到流水线里。
好了,压测环境搭建就聊到这。记住一句话:环境选对了,压测就成功了一半。剩下的,就是怎么设计压测场景、怎么分析结果了。