4. 吞吐测试的常见场景:Web 服务、数据库、消息队列

做吞吐测试这么多年,我绕不开的三个场景就是 Web 服务、数据库 和 消息队列。说白了,大部分线上系统的瓶颈都藏在这三者里。你想想看,用户请求先打到 Web 层,然后读写数据库,再通过消息队列做异步流转——这一条链路上,任何一个环节吞吐跟不上,整个系统都得跟着卡壳。

我个人习惯把这三个场景拆开测,再串起来分析。因为每个场景关注的点完全不同,工具也不一样。下面我挨个讲讲。

吞吐测试三大场景核心逻辑 Web 服务 QPS · 响应时间 (RT) 并发用户数 · 错误率 工具:JMeter / wrk / Locust 数据库 TPS · 查询延迟 (P99) 连接池 · 慢查询 工具:sysbench / pgbench 消息队列 消息吞吐量 (条/秒) 堆积量 · 消费延迟 工具:Kafka 脚本 / JMeter 核心思路 吞吐测试需结合业务模型设计场景。不同场景关注不同指标, 但核心都是找到系统在特定负载下的最大处理能力与瓶颈点。

4.1 Web 服务吞吐测试

Web 服务是最直接面对用户的层,吞吐一掉,用户立马感知到“页面转圈”。我一般先看 QPS(每秒请求数) 和 RT(响应时间) 这两个指标。它们是一对冤家——QPS 往上冲,RT 必然跟着涨。关键是要找到那个“拐点”。

核心指标速查

  • QPS:每秒成功处理的请求数,代表吞吐量。
  • RT(响应时间):平均响应时间 + P99(99% 请求的耗时)。
  • 并发用户数:系统同时维持的连接数,不是越大越好。
  • 错误率:5xx、4xx 比例,超过 1% 就要警惕。

常用的工具有 JMeter、wrk、Locust。我个人习惯先用 wrk 做一轮快速压测,因为它够轻量,几秒钟就能出一组数据。下面是一个典型命令:

# 用 12 个线程保持 400 个并发连接,压 30 秒
wrk -t12 -c400 -d30s http://your-api.example.com/health

输出会直接告诉你 QPS、平均延迟、P99 延迟。看到 P99 飙升的时候,基本就是系统快扛不住了。

小经验: 我曾经在生产环境遇到一个怪现象——QPS 刚到 2000 就疯狂报错,查了半天发现是 upstream 的 keepalive 配置太小。调大之后吞吐直接翻倍。所以 Web 测试别光盯着业务代码,网关、连接池、超时配置这些“边角料”往往才是瓶颈。

4.2 数据库吞吐测试

数据库层往往是最难扩的。Web 服务可以随便加实例,但数据库的吞吐天花板来得很快。我测数据库主要看 TPS(每秒事务数) 和 查询延迟(尤其是 P99)。

有一个坑我印象特别深——连接池。很多人以为连接池越大吞吐越高,其实不是。连接池太大,反而导致上下文切换频繁,延迟飙升。我记得有一次帮一个团队做 MySQL 压测,他们把连接池调到 200,TPS 反而比 50 的时候还低。后来逐步往下调,最后在 32 左右找到了最佳点。

注意: 数据库吞吐测试一定要区分“读写混合”和“只读”场景。线上大部分是读写混合,但很多压测只跑只读,结果跟上线后的表现完全对不上。

工具方面,我常用 sysbench(MySQL)和 pgbench(PostgreSQL)。下面是一个 MySQL 的典型压测命令:

# 32 个线程跑 60 秒的读写混合负载
sysbench --threads=32 --time=60 \
  --tables=10 --table-size=1000000 \
  oltp_read_write run

输出会显示每秒事务数、延迟百分位、每秒查询数等。重点关注 95% 和 99% 延迟——平均值好看没用,毛刺才要命。

4.3 消息队列吞吐测试

消息队列的吞吐测试,角度跟 Web 和数据库都不太一样。这里核心是 生产端 和 消费端 要分开测,再测联调。

我一般先测生产者:往队列里猛写消息,看它能撑到多少条每秒,同时观察延迟有没有抖动。然后再测消费者:从一个已经堆积了大量消息的队列里拉数据,看消费速率能不能跟上。说白了,就是看两端各自的上限在哪里。

消息队列吞吐关键指标

  • 消息吞吐量:生产和消费的速度,单位条/秒。
  • 堆积量:未被消费的消息总数,反映消费端是否滞后。
  • 消费延迟:从消息产生到被消费的时间间隔。
  • 分区/分片数:Kafka 等系统的并行度上限。

Kafka 自带的压测脚本就很实用:

# 测试生产者吞吐(以 1000 字节每条消息为例)
kafka-producer-perf-test.sh \
  --topic test-topic \
  --num-records 1000000 \
  --record-size 1024 \
  --throughput -1 \
  --producer-props bootstrap.servers=localhost:9092

# 测试消费者吞吐
kafka-consumer-perf-test.sh \
  --topic test-topic \
  --messages 1000000 \
  --broker-list localhost:9092

避坑: 我曾经在压 Kafka 消费者时遇到一个怪事——每次跑完数据都很漂亮,但一上线就消费滞后。后来发现是压测时分区都集中在同一个 broker 上,而线上是分布式的。所以测消息队列,分区分布和网络拓扑一定要跟生产环境一致,否则数据根本不准。

三个场景的对比与联动

下面这张表我经常用来给团队做培训,把三个场景的侧重点放在一起看,差距一目了然:

维度 Web 服务 数据库 消息队列
核心指标 QPS / RT / 并发数 TPS / 查询延迟 / 连接池 消息吞吐 / 堆积量 / 消费延迟
主要瓶颈 CPU 线程 / 网络 IO / 网关配置 磁盘 IO / 锁竞争 / 缓存命中率 分区数 / 磁盘吞吐 / 消费者处理能力
常用工具 JMeter / wrk / Locust sysbench / pgbench / HammerDB Kafka 脚本 / RabbitMQ 管理插件 / JMeter
测试策略 梯度增加并发,找到拐点 先测单语句,再测混合负载 生产端和消费端分离测试

说实话,这三个场景不是孤立的。Web 服务吞吐上不去,很多时候是数据库拖了后腿;消息队列消费慢了,又会反过来导致 Web 接口超时。我建议你在做全链路压测之前,先把这三个场景各自摸透,这样才能在出问题时快速定位到具体是哪一环掉了链子。

个人习惯: 每接手一个新系统,我都会先拉一份这三个场景的“吞吐基线”——用同样的负载跑一轮,把 QPS、TPS、消息速率记录下来。后面每次发版或者调优之后,再跑一遍对比。有了基线,性能是变好还是变差,一清二楚。