4. 吞吐测试的常见场景:Web 服务、数据库、消息队列
做吞吐测试这么多年,我绕不开的三个场景就是 Web 服务、数据库 和 消息队列。说白了,大部分线上系统的瓶颈都藏在这三者里。你想想看,用户请求先打到 Web 层,然后读写数据库,再通过消息队列做异步流转——这一条链路上,任何一个环节吞吐跟不上,整个系统都得跟着卡壳。
我个人习惯把这三个场景拆开测,再串起来分析。因为每个场景关注的点完全不同,工具也不一样。下面我挨个讲讲。
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、消息速率记录下来。后面每次发版或者调优之后,再跑一遍对比。有了基线,性能是变好还是变差,一清二楚。