QPS、TPS与系统吞吐量:压测与限流实践全解析

发布时间:2026/9/13 15:48:54
QPS、TPS与系统吞吐量:压测与限流实践全解析 做性能测试这些年我最怕看到的就是测试报告上写着一行亮眼的“TPS 5000”然后线上高峰期一过数据库直接打满接口大面积超时。QPS、TPS、系统吞吐量这三个词几乎每个做后端或者测试的同学都见过但真正能讲清楚区别、又能把它们用在压测和限流实践里的人其实并不多。这篇东西不聊教科书定义就聊我实际工作中踩过的坑以及我最终怎么理解这三个指标怎么用JMeter做混合测试怎么给核心交易接口限制TPS。先给刚接触这块的同学说一下这篇内容能解决什么问题第一帮你把QPS、TPS、系统吞吐量这三个概念彻底理清知道它们分别衡量什么什么时候用哪个第二带你识别“指标虚高”的常见陷阱搞清楚为什么压测数字很漂亮一上线就崩第三我会把JMeter混合测试的配置思路完整写出来包括接口比例怎么设、聚合报告怎么看第四给交易接口限流这块我会从算法选型、参数计算到落地方案给出可以直接抄作业的做法。适合后端开发、测试开发、运维同学读也适合正在做系统容量评估的技术负责人参考。1. QPS、TPS、系统吞吐量三个指标一次讲透1.1 QPS每秒请求数衡量“系统响应请求的速度”QPS的全称是Queries Per Second翻译过来就是每秒查询次数。它最早更多用在数据库、搜索引擎场景衡量的是系统一秒内能处理多少个查询请求。后来在Web服务领域大家习惯把HTTP请求也算进来所以现在很多人嘴里说的QPS其实指的是“每秒请求数”也就是每秒能处理多少个HTTP Request。计算公式很简单QPS 总请求量 ÷ 耗时秒数。举个例子你用压测工具对某个接口打了10秒总共打过去10000个请求那么QPS就是10000 ÷ 10 1000。这里有个细节需要注意这个数值是算数平均值它反映的是这段时间内的平均处理速度不反映峰值也不能反映瞬时抖动。QPS适合用在什么场景最常见的是“读多写少”的系统。比如商品详情页、资讯列表、搜索服务用户大部分时间在做查询操作这种场景下QPS就是最直观的容量指标。你可以把它理解成一个餐饮前台的服务员QPS就是服务员每分钟能接待多少个顾客完成点单。如果一分钟能招呼60个顾客那这个前台的QPS就是60。但QPS有个天然短板它只管“一个请求”不管这个请求背后做了什么。有的请求只是查一下缓存很快有的请求要写数据库、发消息队列、调第三方接口很慢。如果只用QPS来衡量一个包含复杂业务逻辑的系统特别容易失真。1.2 TPS每秒事务数衡量“完整业务操作”TPS的全称是Transactions Per Second每秒事务数。这里的关键词是“事务”。一个事务在业务层面通常代表用户完成的一次完整操作而这个操作在系统内部往往要拆分成多个请求。我给你拆个例子。用户在电商App上下了一单从用户视角看这就是“一次下单”。但系统后端实际做了什么至少包括创建订单、扣减库存、锁定优惠券、生成支付单、调用支付网关、回调更新状态。这六个步骤每个步骤都有可能会发起一次甚至多次HTTP调用或者数据库事务。对用户来说这六个请求合在一起才是“一笔成功交易”。所以TPS度量的是这个完整的业务闭环。正因为如此同一个系统里TPS的数值通常比QPS小得多。一般来说一个事务由N个请求组成那么TPS大致等于QPS除以N。但要注意这只是粗略换算因为不同事务包含的请求数量可能不一样有的事务重有的事务轻。比如“浏览商品”和“提交订单”这两个事务对系统资源的消耗完全不同。TPS更适合用来衡量交易类、写操作频繁的系统比如电商、支付、银行核心系统。这类系统的特点是链路过长、涉及多个子系统、单次操作对数据一致性要求高。容量评估的时候只看QPS很难判断系统真实承载能力必须把事务路径整个跑通用TPS说话。1.3 系统吞吐量全局视角的“总处理能力”系统吞吐量这个词在不同语境下含义略有不同。第一种指的是系统单位时间内能处理的总工作量可以用QPS或者TPS来量化第二种指的是数据传输吞吐量比如每秒能处理多少MB数据常见于数据库、消息队列、磁盘系统。我更倾向于把吞吐量理解成系统的“总输出能力”。QPS和TPS是具体的技术指标而吞吐量更像是一个全局概念。比如一个网关集群整体吞吐量可能是每秒处理10万请求分摊到每个节点就变成每秒1万这里说的“每秒10万”就是系统的吞吐能力。有一个很经典的比喻把系统看成一条高速公路。QPS是每个收费口每秒通过的车数TPS是入口到出口完成一次完整通行的速度而系统吞吐量是整条高速路单位时间能承载的总车流量。高速公路能跑多少车取决于最窄的路段、最慢的收费口以及路面上有没有事故堵车。系统也一样吞吐量受到CPU、内存、磁盘IO、网络带宽、数据库连接池、线程池这些资源中最薄弱一环的约束。所以当我们说“这个系统吞吐量不行”本质上是在说“有资源瓶颈卡住了整体处理能力”。找到这个瓶颈才是性能测试的核心目标。为了让你看得更清楚我把三者放在一张表里对比指标英文全称核心含义常用单位适用场景QPSQueries Per Second每秒处理的请求/查询数次/秒读多写少、接口能力评估TPSTransactions Per Second每秒完成的完整事务数笔/秒交易链路、写操作频繁的系统系统吞吐量Throughput单位时间处理的总工作量请求/秒、MB/秒整体容量评估、资源瓶颈定位2. 指标虚高为什么你测出来的数值上线就崩2.1 虚高的五个常见来源很多团队都会遇到这个现象压力测试报告里写得很漂亮开开心心准备迎接流量高峰结果线上刚开始出现流量系统就报警了。我复盘过多次类似问题所谓“指标虚高”通常是这几个原因叠加造成的。第一测试数据太干净。压测如果全部使用热点数据而这些数据又全部命中缓存那么服务端根本不会打到数据库测出来的QPS自然非常高。但线上真实场景里用户查询的数据是离散的缓存命中率可能只有六成大量请求会穿透到数据库层情况就完全不一样了。第二压测场景过于单一。只盯着一个接口打比如只压“查询商品列表”接口测出来的QPS很高。可线上真实的流量模型里有查询、有加购、有下单、有支付回调各种操作混在一起。写操作占用的系统资源比读操作高一个数量级单场景压测完全暴露不了真实瓶颈。第三忽略了用户思考时间。压测工具默认是发完一个请求马上发下一个线程之间不停顿。但真实用户会有浏览、停顿、思考的过程。这导致压测产生的并发压力远大于真实流量测出来的指标其实不是稳态指标而是极限压力下的指标。第四统计口径只选峰值。有的压测报告取的是“最大QPS瞬间值”比如某一秒冲到了3000但整段压测平均只有800。报告只写峰值3000这就属于典型的取巧式汇报。第五没有限制外部依赖。压测期间如果下游服务或者中间件因为压力触发了扩容或者限流策略还没生效系统本身可能已经处于过载状态但压测工具统计的数字看起来并不难看。2.2 怎么识别指标到底虚不虚识别虚高指标我总结了三板斧。先看分位值别只看平均值。QPS/TPS是平均口径但真实的用户体验更关心TP99、TP999。如果TP99已经超过1秒而平均响应时间才200毫秒说明大量请求虽然很快但已经有1%的用户在忍受极慢的响应。这时候平均QPS再高也不能说明系统健康。再看资源使用率是否同步。如果压测报告显示TPS涨得很高但服务端CPU使用率一直没有上去内存、磁盘IO、网络流量都很平静那这个数值多半有水分。高TPS一定伴随着高资源消耗两者长期背离就要怀疑压测请求没有真正到达业务代码层。最后拉长压测周期。压测时间太短比如只跑三分钟系统可能还处于连接池预热、缓存构建、线程池启动的阶段数据不稳定。我自己习惯的做法是至少跑15到30分钟观察吞吐量曲线是否平稳。如果曲线一路向下说明系统在处理变慢初始峰值是“假峰值”。3. JMeter混合测试还原真实流量的关键操作3.1 为什么必须做混合测试单一接口压测只能回答“这个接口自己的极限在哪里”回答不了“线上整体能扛住多少流量”。真实线上流量是多种请求按一定比例混合出现的而且不同接口的处理成本差异巨大。比如电商场景浏览商品和提交订单就完全不是一个量级。只用下单接口的TPS去评估系统容量必然高估只用浏览接口的QPS去反推系统容量必然低估。混合测试的意义就是用贴近生产环境的流量模型去压测系统得出一个相对可信的系统整体吞吐量。这也是最近很多团队在讨论“qps、tps虚高”问题时反复强调的一点——如果你没有做混合测试不要在汇报里声称自己摸清了系统性能上限。3.2 混合测试的配置步骤与细节JMeter做混合测试我推荐用“单线程组 Throughput Controller”的方式因为它最能模拟真实比例。先说具体操作先创建线程组。线程数量按目标并发估算比如要模拟100个并发用户就设置100个线程。Ramp-Up时间建议不小于60秒让压力逐步上升避免瞬间全量压上去导致系统直接被打垮。循环次数可以设置为50或者更多目的是让压测持续足够长的时间。在线程组下添加多个HTTP请求取样器每个取样器对应一个真实接口。比如接口A是查询商品列表接口B是加入购物车接口C是提交订单。关键一步在每个取样器前面加一个Throughput Controller。这个名字容易误导人它其实叫“吞吐量控制器”但它的作用是按百分比分配流量比例。在Controller的Percent Executions里填上预设的百分比Total Executions那一栏设为对应的调度值。比如想让接口A占70%流量就在Controller的Percent Executions里填70。接口B填20接口C填10。三个控制器的Percent Executions加起来要等于100。添加思考时间。在取样器之间加Constant Timer模拟用户阅读页面、犹豫输入的时间推荐设置成2000到5000毫秒。不加思考时间压测强度会比真实流量高很多数据失真。添加聚合报告Aggregate Report。跑完后重点看Throughput列单位是/sec这个数值就是在当前混合比例下系统能够处理的平均事务量。如果每个接口对应一个完整事务这个值就是混合场景下的TPS。实操中还有几个非常影响结果的细节参数不能写死。如果一个接口压测时用的全是同一组参数服务端可能命中缓存导致结果偏高。用CSV Data Set Config加载几百条真实脱敏参数让每次请求的参数都不同更接近线上。断言要加好。不加响应断言JMeter默认只要收到响应就算成功。就算接口返回500也会被计入成功事务。通常我会加一个“响应代码等于200”的断言同时在聚合报告里盯着Error%这一项如果错误率超过0.1%这一轮压测数据就不该采纳。具体配置可以参考下面这个简化的测试计划Test Plan └── Thread Group (线程数100, Ramp-Up 60s, 循环50次) ├── CSV Data Set Config (加载用户参数文件) ├── Constant Timer (思考时间3000ms) ├── Throughput Controller (Percent Executions70) │ └── HTTP Request (查询商品列表) ├── Throughput Controller (Percent Executions20) │ └── HTTP Request (加入购物车) ├── Throughput Controller (Percent Executions10) │ └── HTTP Request (提交订单) └── Aggregate Report3.3 混合测试结果怎么解读混合测试跑完不要只盯着一个数字看要做三层判断。第一层看整体吞吐量。聚合报告里的Throughput乘以压测总时长可以估算出在这个流量模型下系统能处理的请求总量。如果这个数值低于你的业务预期那就要扩容或者做优化。第二层对比各接口的响应时间。如果某一个接口响应时间显著高于其他接口它就很可能是整个系统的瓶颈。比如三个接口中下单接口TP99达到3000毫秒其他接口都是200毫秒那问题大概率出在下单链路依赖的数据库锁、远程调用或者事务处理上。第三层观察吞吐量随并发变化曲线的拐点。JMeter里可以用Server Agent配合PerfMon Metrics Collector监听服务器资源也可以开后端监听器把数据打到监控平台。当并发量继续增加但吞吐量不再上升时这个拐点就是系统真实容量的边界。4. 给某个交易限制TPS限流方案的落地实践4.1 为什么要限制TPS保护系统不被流量打穿很多人有个误区觉得系统性能越强越好为什么要限制我在实际项目中遇到过典型的反面案例某个交易接口没有任何限流保护凌晨大促一开始瞬时流量暴涨数据库连接池被占满所有请求都在等待数据库连接最终导致整个服务雪崩。限制某个交易的TPS本质上是一种保护策略。目的有三个第一保护下游资源。数据库、第三方支付接口、消息中间件它们能承受的并发有限。上游接口不限制流量下游瞬间被打死整个链路全挂。第二削峰填谷。流量往往是突刺型的几秒钟内冲上来一大波正常时期又很空闲。限流可以把突刺流量延后处理让系统在处理能力范围内平滑处理。第三防止故障扩散。单条交易链路被流量打垮后如果没有限流故障会沿着调用链传导拖垮其他服务。4.2 常见限流算法选型限流算法有四种主流方案我直接对比一下算法基本原理优点缺点固定窗口按固定时间窗口计数超过阈值就拒绝实现简单内存开销小窗口临界点可能瞬间双倍流量滑动窗口将时间窗口细分细粒度计数解决固定窗口临界突刺问题实现复杂度略高漏桶请求先进入桶中以固定速率流出流量绝对平滑适合保护下游无法应对突发流量可能导致大量请求排队令牌桶以固定速率生成令牌请求需拿到令牌允许一定突发流量兼顾平滑与弹性突发量需要合理配置桶容量从我自己的实践看交易类接口最常用的是令牌桶。为什么交易场景经常有脉冲式流量比如整点秒杀那一刻流量暴增令牌桶可以在桶里积攒一些令牌允许短时间内冲破平均速率同时又不会无限放纵流量。而漏桶更适合流量必须绝对平滑的场景比如消息推送。选型之后的参数计算才是真正体现功底的地方。限流阈值不是拍脑袋定的我一般按三步走。第一步基于压测数据取底线。用混合测试得到的该交易接口TPS作为基准值通常限制在这个值的60%到80%。比如混合测试中下单接口的TPS大约是1000那限流阈值先定在700左右。第二步校验下游容量。如果下游数据库连接池最大是50个连接单个下单事务平均占用连接10毫秒那么理论上限是50 ÷ 0.01 5000 TPS。但这是理想值实际要打个五折压到2500以内。限流阈值不能超过这个数不然压测指标上去了数据库先顶不住。第三步加安全缓冲。如果系统还有其他流量会争抢公共资源比如同一个数据库还有其他业务在用还要再往下调。经验值是在核算出的理论值上再打七折。4.3 落地方案两种限流实现方式先看基于Guava RateLimiter的本地限流方案适合单机应用或者分布式场景下配合网关统一使用。// 创建限流器每秒发放20个令牌即TPS限制为20 RateLimiter limiter RateLimiter.create(20.0); // 方式一阻塞式 // 调用者会等待直到获取到令牌适合后台任务、异步消费 limiter.acquire(); // 方式二非阻塞式 // 一秒内尝试获取1个令牌抢不到就直接拒绝适合实时交易 if (limiter.tryAcquire(1, 1, TimeUnit.SECONDS)) { // 执行下单业务逻辑 } else { // 返回“系统繁忙请稍后重试” throw new BizException(当前下单量过大请稍后再试); }这里有一个容易踩的坑如果直接用acquire()阻塞获取令牌在高并发下会导致大量请求线程全部挂起等待线程池被占满其他接口也一起卡死。所以对实时交易类接口我建议优先用tryAcquire非阻塞方式抢不到令牌就让请求快速失败让客户端重试。再看看基于Sentinel的分布式限流方案。网关层的每个节点都会收到真实流量本地限流在集群环境下无法形成统一阈值需要用Sentinel这种集中管理的方式。private void initFlowRule() { ListFlowRule rules new ArrayList(); FlowRule rule new FlowRule(); // 资源名对应受保护的交易方法 rule.setResource(order:create); // 根据QPSgrade1进行限流 rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // 阈值每秒最多100个下单请求 rule.setCount(100); // 直接拒绝超过阈值立即失败 rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT); rules.add(rule); FlowRuleManager.loadRules(rules); }Sentinel除了直接拒绝还支持匀速排队模式也就是做削峰。把controlBehavior改成CONTROL_BEHAVIOR_RATE_LIMITER并设置一个超时时间比如500毫秒超过500毫秒还拿不到令牌的请求就直接拒绝。这个模式很适合保护数据库让流量平滑地进入系统避免瞬间冲击。4.4 限流阈值调整的实战心得限流阈值不是设置一次就完事的需要持续观察调整。我经历过一个案例给某交易接口设了1000TPS的阈值大促前流量预估也就800左右结果实际期间流量突刺到了1200因为阈值偏低部分用户收到了“系统繁忙”的提示。事后复盘才发现最开始是因为单机压测只能扛住800但压测时没有使用混合流量模型低估了系统真实能力。后来我们把混合测试重新做了一遍发现整体吞吐量在1300左右于是把阈值调整到1100同时加上了Sentinel的匀速排队模式给下游数据库留出处理的喘息空间。调整之后用户体验明显回升数据库也没有出现连接池打满的情况。所以我的建议是限流阈值要有“压测数据 线上监控 人工修正”三个输入。压测数据是基础线上监控是验证人工修正是根据业务容忍度做最终决定。5. 性能指标相关的常见问题排查实录5.1 问题与排查速查表把这些年遇到的典型问题整理成一张表方便你遇到类似情况时快速定位问题现象可能原因排查思路压测TPS很高上线性能差压测场景过于单一未混测重新做混合测试按真实流量比例压测压测中TPS曲线持续下降连接池被打满线程阻塞GC频繁查看数据库连接池监控、线程dump、GC日志平均响应时间正常但TP99极高存在少量慢查询或长尾请求分析慢SQL、外部调用耗时、是否有大对象创建限流触发后大量请求直接失败限流策略选择的是直接拒绝改为匀速排队模式或加入重试机制聚合报告显示错误率偏高断言设置不当或参数化数据用尽检查断言条件和CSV数据量观察返回错误码分布吞吐量在高并发下上不去单线程瓶颈或锁竞争结合火焰图定位热点检查是否有多线程争锁问题5.2 压测与限流的避坑建议第一压测之前先做脚本验证。我见过不少新手直接上来就跑全量压测结果发现接口参数写错所有请求都返回500还对着聚合报告分析半天。正确做法是先设置1个线程、循环1次跑通脚本确认断言通过、响应正常再逐步往上加压。第二压测环境要与生产环境同规格。如果压测用的是4核8G的机器生产是8核16G压测出来的TPS根本没法直接换算。至少保证CPU核数、内存容量、数据库配置保持一致否则数据没有参考价值。第三压测必须记录服务端监控。只记录压测端的吞吐量和响应时间是不够的还要记录服务端的CPU、内存、磁盘IO、GC频率、数据库连接池使用率。这些数据决定了压测结论的可信度也是后续调优的依据。第四限流要考虑用户体验与系统保护的平衡。限流值设得过低用户频繁收到失败提示设得过高系统保护形同虚设。我通常的思路是优先保护核心资源比如数据库连接池和第三方依赖再根据业务容忍度调整限流值。第五对不同交易设置差异化限流。不是所有交易都用同一套限流核心逻辑。有些交易是用户主动发起的比如下单、支付直接拒绝会严重影响体验有些交易是系统内部发起的比如消息重试、定时任务这些即使排队等待也不会对用户造成直接影响。给内部交易设置更保守的限流给用户交易留出更多余地整体稳定性会好很多。5.3 一个混合测试与限流的联动案例最后分享一个完整的实操链路方便你把前面几部分串起来看。我们当时给一个积分兑换系统做容量评估。业务方给出的预期是大促期间最高峰每秒大约有500个用户提交积分兑换请求同时有2000个用户浏览积分商品页。我先用JMeter搭了混合场景浏览接口和兑换接口的流量比例设置为4比1跑下来发现系统整体吞吐量大约在1900QPS看起来是够用的。但再看分项数据兑换接口的聚合报告里错误率达到0.8%原因是兑换接口内部调用了库存服务库存服务在并发达到一定量级后频繁超时。这就暴露出真实的瓶颈不在应用层而在下游库存系统。于是我们给兑换接口单独做了一轮压测确认它在无保护状态下的极限是300TPS但库存服务只允许150TPS。确认瓶颈后我们在积分兑换服务上用Sentinel给兑换接口设置了130TPS的限流阈值同时启用了匀速排队模式。上线后大促期间兑换接口的TPS稳定在120左右库存系统没有报警用户体验也保住了。这个案例想说明一个道理性能指标从来都不是一个孤立的数字。测出系统的QPS、TPS只是第一步理解指标背后的资源消耗和链路依赖再用限流手段把系统稳定在安全区间内才是完整的能力闭环。我个人在实际操作中还有一个体会永远不要对着一个压测报告下结论。同样的TPS数字如果承载它的资源水位不同业务链路复杂度不同对系统的真实意义就完全不同。多问一句“这个数字是在什么条件下测出来的”比记住任何性能指标的定义都更有用。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询