压力测试原理:吞吐量、延迟、并发模型

做压测,说白了就是想知道你的系统到底能扛多少活儿。但“活儿”这个词太模糊了——是每秒能处理多少请求?还是响应快不快?还是同时能撑多少人?我刚开始搞PKI证书SDK压测那会儿,也把这些概念混着说,后来才发现,三个指标各管各的,理不清它们的关系,报告根本写不明白。今天咱们把这三个东西一个一个拆开看看。

吞吐量:系统能“产”多少

吞吐量,通常记作TPS(每秒事务数)或者QPS(每秒查询数)。在PKI证书场景里,一个事务就是签发一张证书、吊销一张证书、或者验证一次证书状态。你想想看,如果你的SDK跑在CA服务器上,用户发一个证书签发请求,从收到请求到返回证书,这个完整过程就算一个事务。

我个人习惯这样定义:吞吐量 = 单位时间内成功完成的事务数量。注意“成功”两个字——那些返回了错误但没完成的,不能算。我在一个项目中遇到过,客户端超时断开连接,服务端其实已经生成了证书,但客户端没收到。这种情况吞吐量就只算客户端成功接收的部分,否则你会高估系统的真实能力。

关键点:吞吐量是衡量系统处理能力的核心指标。压测时我们一般关注“最大稳定吞吐量”——也就是系统在长时间运行下,不出现错误或严重抖动的那个吞吐值。

延迟:用户要等多久

延迟,也叫响应时间,是指从发送请求到收到完整响应所花费的时间。对于PKI证书签发来说,可能包括网络传输、SDK签名运算、数据库写入等各个环节。一般我们会统计平均延迟、P50、P99甚至P999延迟。

为什么看P99比看平均更重要?举个例子:一次压测里,99%的请求都在50ms内完成,但有1%的请求因为GC停顿或数据库锁,花了500ms。平均下来可能只有55ms,看着不错对吧?但实际使用中,那1%的慢请求可能就是你的大客户在等待,用户体验极差。我建议你们在报告里至少放三个分位数:P50、P99、P999。

避坑:我曾经遇到一个情况,SDK内部把失败重试也算在了延迟里——重试三次才成功,延迟显示1200ms,但首次成功其实只要400ms。这样会把真实性能掩盖掉。所以计算延迟时,要排除重试和异常分支,只统计“干净的成功请求”。

并发模型:系统能同时服务多少人

并发,简单说就是同一时刻系统中处于活动状态的请求数。注意“活动状态”——不是指连接数,而是正在被处理中的请求。并发模型决定了系统怎么分配资源(线程、协程、连接池等)。

对于PKI证书SDK,最常见的是同步阻塞模型(一个请求占一个线程)和异步模型(少量线程处理大量请求)。同步模型好理解,但并发上不去;异步模型吞吐高,但延迟可能不稳定。我实际压测过一个Java写的SDK,默认用线程池,并发数一超过200,CPU没满,但线程切换开销就把延迟推高了。后来改成协程模型,同样硬件,稳定并发从200提到800。

并发模型最大并发数稳定性典型场景
同步阻塞(BIO)低(受线程数限制)中传统CA接口
事件驱动(NIO/协程)高(千级以上)高高并发证书验签
混合模型中高高证书签发+数据库写

三者关系:利特尔法则

吞吐量、延迟、并发之间有一个铁三角关系,用利特尔法则可以表达:

吞吐量 = 并发数 / 平均延迟

这个公式非常有用。比如你测出来平均延迟是50ms,并发数是100,那么理论吞吐量就是100 / 0.05 = 2000 TPS。如果实际压测吞吐量只有1800,那说明系统里存在额外的排队或阻塞,没有100%利用资源。

实用技巧:压测时可以先固定并发数,调整负载观察延迟变化;也可以固定目标延迟,逐步增加并发,直到吞吐量不再增长——那个拐点就是系统的最优工作点。

但是在真实PKI证书场景里,这三个指标不是独立的。比如证书签发过程涉及私钥运算,CPU是瓶颈;而证书状态验证可能IO更多。不同场景下,瓶颈不同,三者之间的比例关系也会变。我建议你们每次压测都记录完整的并发-吞吐-延迟曲线,而不是只给一个平均值。

压力测试三要素与利特尔法则 吞吐量 TPS/QPS 延迟 响应时间 / 分位数 并发 活动请求数 影响 决定上限 利特尔法则:吞吐量 = 并发 ÷ 平均延迟 🔑 铁三角关系 增加并发 → 延迟上升 → 吞吐量先升后降 降低延迟 → 吞吐量上升(同等并发下) 目标是找到低延迟、高吞吐、可承受并发的平衡点

嗯,上面这张图把三个指标串起来了。你可能会问:为什么并发和延迟之间是相互影响的关系?其实很好理解——并发高了,资源竞争加剧,每个请求等待的时间就变长,延迟自然上去;反过来,如果每个请求处理得慢,系统在那段时间里同时处理的请求数也会增多(队列积压),所以实际并发也会被动变大。

最后说一个我在实际项目中踩过的坑。有一回我们压测证书验证接口,并发从100逐步加到500,吞吐量一直线性上升,很开心。但加到800的时候,突然延迟从20ms飙到2s,吞吐量反而下降了。为什么?因为连接池满了,请求开始排队,相当于系统进入了“过载保护”状态。后来我们调整了连接池大小和请求超时策略,才让系统在更高并发下稳定运行。所以——压测不只是跑一个吞吐量数字,而是搞清楚系统在什么背景下能做什么事。这一点,贯穿我们整个PKI证书SDK压测优化的所有环节。