4. 压测工具选型:主流压测工具对比与实战配置

说到压测工具选型,我见过不少团队在这个问题上纠结很久。有的盲目追求高性能工具,结果脚本写起来痛苦不堪;有的选了最易上手的,压到一半发现并发上不去。说白了,没有最好的工具,只有最适合你场景的。

这一章,我就结合自己这些年踩过的坑,把主流工具掰开揉碎了讲清楚。你想想看,选错工具的代价是什么?可能是整个压测周期延长一倍,甚至得出错误的性能结论。

4.1 主流压测工具横向对比

先看一张我整理的对比表,这样你心里有个大概的谱:

工具 语言 协议支持 并发模型 脚本复杂度 分布式支持 学习曲线
JMeter Java HTTP/HTTPS/WebSocket/JDBC/自定义 线程池 低(GUI拖拽) 原生支持
Locust Python HTTP/HTTPS/自定义 协程(gevent) 中(Python代码) 原生支持
Gatling Scala HTTP/HTTPS/WebSocket/JMS Akka Actor 高(DSL脚本) 原生支持
wrk C/Lua HTTP/HTTPS 事件驱动(epoll) 低(命令行+Lua) 需第三方

4.2 逐个拆解:我的实战感受

JMeter — 老牌劲旅,但别被GUI骗了

JMeter是我最早接触的压测工具。说实话,它的GUI界面确实友好,拖拖拽拽就能生成脚本。但我在项目中遇到过一个大坑:GUI模式下的压测结果不准。为什么呢?因为GUI本身会消耗系统资源,尤其是线程数上去后,JMeter自己先成了瓶颈。

避坑指南:我曾经在压测一个电商系统的登录接口时,用GUI模式跑了500并发,结果TPS只有800。换成命令行模式(非GUI),同样配置下TPS直接飙到1500。记住:生产级压测永远用命令行

JMeter的优势在于协议支持广泛。除了HTTP,它还支持JDBC、JMS、WebSocket等。如果你需要压测数据库或者消息队列,JMeter几乎是唯一的选择。

安装很简单,去官网下载二进制包,解压就能用:

# 下载JMeter
wget https://dlcdn.apache.org//jmeter/binaries/apache-jmeter-5.6.3.tgz
tar -xzf apache-jmeter-5.6.3.tgz
cd apache-jmeter-5.6.3/bin

# 启动GUI(调试用)
./jmeter

# 启动命令行(压测用)
./jmeter -n -t test_plan.jmx -l results.jtl -e -o report_dir

Locust — Python党的最爱

我个人习惯用Locust做快速验证。它的核心思想是用Python代码描述用户行为,非常灵活。你想想看,如果被测接口需要先登录获取token,再携带token访问业务接口,用JMeter的BeanShell脚本写起来多痛苦?Locust几行代码就搞定了。

from locust import HttpUser, task, between

class WebsiteUser(HttpUser):
    wait_time = between(1, 5)  # 模拟用户思考时间
    
    def on_start(self):
        # 登录获取token
        resp = self.client.post("/login", json={"user": "test", "pass": "123"})
        self.token = resp.json()["token"]
    
    @task(3)
    def view_home(self):
        self.client.get("/home", headers={"Authorization": f"Bearer {self.token}"})
    
    @task(1)
    def view_profile(self):
        self.client.get("/profile", headers={"Authorization": f"Bearer {self.token}"})

Locust的并发模型基于协程(gevent),这意味着单机就能轻松模拟数千并发。我在项目中用一台4核8G的云服务器跑Locust,压到5000并发都没问题。换成JMeter,同样配置可能到2000就开始报OOM了。

小技巧:Locust的Web UI非常直观,可以实时调整并发数和生成速率。我经常在压测开始后,一边观察系统指标,一边动态调整压力,直到找到系统的拐点。

Gatling — 高性能但门槛高

Gatling是我见过性能最猛的压测工具之一。它基于Akka Actor模型,天生就是为高并发设计的。我记得有一次压测一个直播平台的弹幕接口,JMeter跑到3000并发就开始丢数据,换成Gatling轻松跑到8000并发,而且结果曲线非常平滑。

但Gatling的脚本是用Scala DSL写的,学习曲线确实陡。你看这个脚本:

import io.gatling.core.Predef._
import io.gatling.http.Predef._

class BasicSimulation extends Simulation {
  val httpProtocol = http
    .baseUrl("https://api.example.com")
    .acceptHeader("application/json")
  
  val scn = scenario("Basic Scenario")
    .exec(http("request_1")
      .get("/users")
      .check(status.is(200)))
  
  setUp(
    scn.inject(atOnceUsers(100))
  ).protocols(httpProtocol)
}

说实话,如果不是团队里有Scala基础的人,我不建议轻易上Gatling。但如果你需要压测WebSocket或者JMS协议,Gatling的DSL表达能力确实比JMeter强很多。

wrk — 轻量级利器,适合快速压测

wrk是我最常用的快速压测工具。它基于epoll事件驱动模型,单机就能压出很高的并发。安装也简单:

# 安装依赖
sudo apt-get install build-essential libssl-dev

# 编译安装
git clone https://github.com/wg/wrk.git
cd wrk
make
sudo cp wrk /usr/local/bin/

# 快速压测
wrk -t12 -c400 -d30s https://api.example.com/users

这个命令的意思是:用12个线程,保持400个并发连接,持续压30秒。输出结果非常简洁:

Running 30s test @ https://api.example.com/users
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    45.67ms   12.34ms  189.00ms   75.00%
    Req/Sec     734.56    89.23     1.02k     70.00%
  263456 requests in 30.00s, 1.02GB read
Requests/sec:   8781.87
Transfer/sec:     34.78MB

wrk的缺点也很明显:只支持HTTP/HTTPS协议,而且脚本能力弱。虽然可以用Lua脚本做一些简单的请求定制,但复杂场景基本没戏。我一般用它来做接口的基准测试,快速判断一个接口的性能基线。

4.3 工具选型考量因素

说了这么多,到底怎么选?我总结了一个决策框架:

  1. 协议类型:如果只压HTTP,wrk或Locust就够了。如果需要JDBC、JMS等,只能选JMeter或Gatling。
  2. 并发规模:单机5000并发以内,Locust性价比最高。超过5000,考虑Gatling或分布式JMeter。
  3. 团队技术栈:Java团队选JMeter,Python团队选Locust,Scala团队选Gatling。别为了工具换语言,成本太高。
  4. 报告需求:JMeter和Gatling自带HTML报告,Locust需要配合InfluxDB+Grafana。如果客户要求漂亮的报告,Gatling的图表最专业。
  5. 持续集成:JMeter有Maven/Gradle插件,Gatling有sbt插件,Locust可以直接用Python的unittest框架。选跟你们CI/CD流水线集成最方便的。

我的建议:团队至少掌握两个工具。一个轻量级的(wrk或Locust)做快速验证,一个重量级的(JMeter或Gatling)做全链路压测。我自己是「Locust + JMeter」组合,覆盖了90%的场景。

4.4 工具安装与基础配置

这里我给出最常用的安装方式,避免你走弯路。

JMeter 安装配置

# 1. 安装JDK(JMeter需要Java 8+)
sudo apt-get install openjdk-11-jdk

# 2. 下载JMeter
wget https://dlcdn.apache.org//jmeter/binaries/apache-jmeter-5.6.3.tgz
tar -xzf apache-jmeter-5.6.3.tgz -C /opt/

# 3. 配置环境变量
echo 'export JMETER_HOME=/opt/apache-jmeter-5.6.3' >> ~/.bashrc
echo 'export PATH=$JMETER_HOME/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

# 4. 验证安装
jmeter --version
性能调优:JMeter默认堆内存只有512MB,压测时很容易OOM。建议修改jmeter.sh中的HEAP设置:HEAP="-Xms4g -Xmx8g -XX:MaxMetaspaceSize=512m"

Locust 安装配置

# 使用pip安装
pip install locust

# 验证安装
locust --version

# 启动(Web UI模式)
locust -f locustfile.py --host=https://api.example.com

# 启动(无头模式,适合CI/CD)
locust -f locustfile.py --host=https://api.example.com --headless -u 1000 -r 100 --run-time 5m

Gatling 安装配置

# 下载Gatling
wget https://repo1.maven.org/maven2/io/gatling/highcharts/gatling-charts-highcharts-bundle/3.11.5/gatling-charts-highcharts-bundle-3.11.5.zip
unzip gatling-charts-highcharts-bundle-3.11.5.zip -d /opt/

# 进入目录
cd /opt/gatling-charts-highcharts-bundle-3.11.5

# 运行示例压测
./bin/gatling.sh

# 运行自定义压测
./bin/gatling.sh -s com.example.BasicSimulation

wrk 安装配置

# 编译安装(前面已讲)
# 常用参数说明
wrk -t<线程数> -c<连接数> -d<持续时间> <URL>

# 使用Lua脚本定制请求
wrk -t4 -c200 -d30s -s post.lua https://api.example.com/login

嗯,到这里四种工具的安装和基础配置就讲完了。你可能会问:「我到底该先学哪个?」我的建议是:先学Locust,因为它上手快、Python生态好、单机性能强。等你把压测流程跑通了,再根据实际需求去学JMeter或Gatling。

最后送你一句话:工具只是手段,理解系统瓶颈才是目的。别在工具选型上浪费太多时间,先跑起来再说。


公众号:蓝海资料掘金营,微信deep3321