三、压测环境搭建:单机、分布式与容器化

说到压测环境搭建,我见过太多团队在这上面栽跟头了。有人用笔记本压线上服务,结果网络延迟先成了瓶颈;有人一上来就搞几十台机器集群,最后发现单机就能搞定。说白了,环境搭建这事,得看你的目标是什么。

我个人习惯把压测环境分成三类:单机、分布式、容器化。每种都有它的适用场景,也有它的坑。今天咱们一个一个聊。

3.1 单机压测环境

单机压测,就是在一台机器上跑压测工具。比如你用 JMeter 或者 wrk,在本机发请求压本机或远程服务。

什么时候用单机?

  • 接口数量少,QPS 预期不高(比如几千以内)
  • 快速验证功能,比如看看接口通不通、响应时间对不对
  • 开发自测阶段,不想折腾复杂环境

我踩过的坑: 有一次我用笔记本压一个本地服务,结果 CPU 被打满了,压测结果惨不忍睹。后来才发现,压测工具和被测服务抢资源了。你想想看,一台机器既要发请求又要处理请求,结果能准吗?

注意: 单机压测时,压测工具所在机器的资源(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
关键点: Master 和 Slave 之间网络要通,时间要同步。我遇到过 Slave 时间差了 5 秒,结果聚合出来的响应时间全是错的。

分布式压测的注意事项:

  • 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
小技巧: 用 Docker Compose 的 depends_on 控制启动顺序。Master 要等 Slave 都启动后再开始压测。我一般会在 Slave 启动后加个健康检查,确保服务真的就绪了。

容器化压测的优势:

  • 环境一致:开发、测试、生产用同一套镜像
  • 快速扩展:加一个 Slave 就是加一行配置
  • 资源隔离:每个容器独立,互不影响
  • 易于清理:压测完直接 docker-compose down

我踩过的坑: 有一次用容器化压测,发现结果比物理机差很多。排查了半天,原来是 Docker 的网络模式问题。默认的 bridge 模式有 NAT 转换,增加了延迟。后来改成 host 模式,结果就正常了。

注意: 容器化压测时,网络模式要选对。追求性能就用 host 模式,追求隔离就用 bridge 模式。另外,容器内的资源限制(CPU、内存)也要设置好,否则一个容器可能把宿主机资源吃光。

3.4 三种环境的对比

维度 单机压测 分布式压测 容器化压测
适用场景 快速验证、低并发 高并发、多 IP 模拟 CI/CD、微服务、快速部署
部署复杂度 低 中 中高(需 Docker 基础)
扩展性 差 中 好
环境一致性 差 中 好
资源开销 低 高 中
结果准确性 中(受压测机影响) 高 高(需注意网络模式)

3.5 知识体系图

下面这张图,是我梳理的压测环境搭建的核心逻辑。你可以把它当成一个决策树,看看自己该选哪种方式。

压测环境搭建决策树 压测环境选择 单机压测 分布式压测 容器化压测 适用条件 QPS < 5000 快速验证、开发自测 适用条件 QPS > 10000 多 IP 模拟、复杂场景 适用条件 CI/CD 集成 微服务、快速部署 注意事项 压测机资源不能成瓶颈 并发数建议 < 1000 结果可能不准确 注意事项 Slave 配置要一致 时间必须同步 Master 内存要够 注意事项 网络模式选 host 设置资源限制 注意健康检查

这张图其实挺直观的。你从根节点开始,根据你的场景往下走,就能找到合适的方案。我个人建议:如果团队有 Docker 基础,直接上容器化方案。省心、好维护,而且容易集成到流水线里。

好了,压测环境搭建就聊到这。记住一句话:环境选对了,压测就成功了一半。剩下的,就是怎么设计压测场景、怎么分析结果了。

可可精品资料库