性能常识 性能测试中大家是用线程数还是 TPS 解释这个并发这一个概念的

wchzs · 2022年04月11日 · 最后由 下午去踢球 回复于 2024年11月21日 · 9166 次阅读

目前待过几家中小公司,几个测试团队几乎已线程数来描述系统的并发。但感觉这样很不准确。

需求:登录接口能够承受秒级 1000 并发

假设并发理解为线程的话,1000 线程持续执行 60 秒,结果理论上应该产出 60000 条数据才符合需求

假设并发理解为 TPS 的话,可能花 30 个线程就可以达到 1000tps 执行 60 秒,结果也能产出 60000 条数据

大家是按什么来理解并发这个概念的

共收到 24 条回复 时间 点赞

一般情况下,在做性能测试时,都不会去强调并发的概念。因为现实的场景中,除了秒杀、整点开抢等几类特殊的场景外。都不会进行狭义上的并发测试。与实际的业务场景不符。我们更多的会采用 TPS,响应时间之类的指标来衡量性能。

“登录接口能够承受秒级 1000 并发” 这个性能需求本身就有问题。秒级 1000 并发,也就意味着 TPS 达到 1000(如果是这么理解的话)。那么线程数是多少并不是固定的。因为还要考虑到响应时间。

如果按上面的理解,TPS 要求达到 1000,假设响应时间为 0.5,那就是要 500 的请求量(TPS = Vu/Time,这里暂不考虑网络传输的时间,实际情况会更复杂),至于这 500 的请求量,是通过 50 线程的并发,还是 100 线程的并发,并不重要。因为对于服务器而言,关心的单位时间内到达服务器的请求数,至于这些请求是由多少线程发起的,并不太关心。

不要纠结并发数,TPS 结合响应时间,才是性能的真实指标

Tps 是服务器每秒处理的事务数量,跟多少个线程没有任何关系。多线程只为了产生更大的 rps,而 tps 不可能大于 rps。多线程并发在单核 cpu 上其实是交替执行的,只是切换时间很短,以纳秒计,所以看作是同时运行,这称为并发。还有一个相似的概念叫并行,必须不同的线程运行在不同的 CPU 核心上

TPS,代表服务端的并发处理能力。
jmeter 中有个 Number of Thread 指的是并发用户数。
这两个很容易混淆。
性能测试关注的是 TPS、响应时间和错误率。

tps 是加入了响应时间后计算出来的吧?我理解的是线程数越多 qps 越高,但是 tps 是有个瓶颈的,超过了瓶颈,线程数再多也上不去了,然后超时,错误之类的会增加

并发只是提高 TPS 或 QPS 的一种手段,实际操作中线程数=并发数,但是不等于处理并发能力

秒级 1000 并发需求可以有两种理解:

  1. 场景可以支持 1000QPS 或 TPS,不论是高并发还是低并发,能达到就可以(达不到加资源),同时观察响应时间和错误率在合理范围内,给出达到预期的最小并发,另外如果资源冗余再看下资源能支撑的最高并发以及可达到的最高 TPS 或 QPS,评估是否符合预期(适用于流量高峰持续场景)
  2. 当前资源下、1000 并发场景下的服务能力在合理范围(响应时间、错误率、资源指标),直接起 1000 并发,看资源情况(适用于秒杀活动那种场景)

这种都要结合实际的性能测试需求,看是哪一种再决定怎么做,不用纠结于字眼。以登陆接口为例的话,我理解更多的是 1000QPS 的概念,而不是 1000 个并发。

两个数据都很重要。

TPS 是最直观的表明服务性能能力的一个指标,但是同样一个服务,在 1000 并发下和 2000 并发下的性能表现可能会差距很大。 1000 并发和 2000 并发对于服务来说,表示不同的连接压力。

举个例子:当服务最大处理能力为 1000TPS 时,当 1000 个并发压测时,平均响应时间为 1 秒。
但是当 2000 个并发压测时,因服务处理能力有限,平均响应时间可能会增加到 1.5 秒。

这个时候,当并发继续增加的时候,服务很可能出现性能拐点(QPS 大幅下降,响应时间大幅增加)。


所以,在日常压测中,开发同学还需要考虑,当大量并发链接请求来临时:
(1)是否会出现性能拐点
(2)到达性能拐点之前,是否需要增加降级方案
(3)对于易引发性能问题的并发数,是否要增加细粒度报警
等等
以及:
(1)在目前的基础上,是否可通过调整配置,来提高服务的 TPS 能力和应对并发的能力

CKL的思考 回复

确实是这样,但是现在很多团队还有领导,都认为并发数这个概念是以线程数或者用户数来判定,想要在团队里改变这种观念太难了,甚至有次出完性能报告给甲方后,甲方又找了家第三方有测试资质的机构再次测试了一遍性能,一看第三方的报告,1000 并发就是 1000 个线程,给我整不会了都😅

回复

比如我 1000 个线程持续压测,但此时 tps 是 100,在某个时间点,有 100 个线程在服务里面,那剩下的 900 个线程是在哪个位置排队呢,在 nginx 里面还是其他地方呢

wchzs 回复

这是什么理解,用 1000 个线程压测,服务端当然得有 1000 个线程,压测首先要监测服务端增加的线程数跟发起的线程数一致,你都说 tps 是算出来的来表达服务端能力的,跟线程无关。然后你的疑惑我认为可以从业务角度出发,性能测试也是要尽量模拟真实场景对吧,那么同样 1000tps 的登录接口:

1、1000tps = 1000 个用户 1s 内每个用户登录一次
2、1000tps = 100 个用户 1s 内每个用户登录十次

这两个一样吗,是不是还是用 1000 个用户比较接近实际,而且是领导们更关注的是场景 1 我觉得没啥问题。

再一个从实际出发,100 线程想达到 1000 的 tps,那每 s 每个线程都要完成 10 个请求,每个请求只有 0.1s,这也不太现实,一般高并发(线程)才能达到高 tps,所以我认为理解 线程数=并发 没有什么问题

本来就不是一个东西。
不过实际工作中,有些可能是描述上的问题,我们产品爱用并发用户数来描述性能,因为他们关心的是客户端用户情况,他们对服务器处理能力说实话有些没有太大的概念,在他们看来是一回事儿。。。所以提的性能指标需求翻译过来可能就是线程数。

但是做性能测试和分析的人得知道差别。

wchzs 回复

首先你应该测出 1000 个线程所产生的 qps,纠正一下,我前面描述有误,rps 应该为 qps,也就是测试出 1000 个线程每秒能发送多少个请求,假如你的 CPU 特别垃圾,1000 个线程只能产生 100 个 qps,那你的 CPU 负荷太高,线程可能处于任何状态。假如 1000 个线程产生的 qps 远远大于 100,那说明 CPU 负载有余,那性能瓶颈在服务器,线程大多在等待服务器响应

个人理解,专业的性能测试人员,应该要用 TPS + 响应时间 来描述服务端性能。包括要达到的性能目标以及实际测试出来的性能结果。

  • 先来解析下你正文里这两个看起来好像等价的假设:

假设并发理解为线程的话,1000 线程持续执行 60 秒,结果理论上应该产出 60000 条数据才符合需求

其实你这句话里面带有一个预设条件,就是每个请求的响应时间大约是 1 秒。要满足这个场景,性能需要达到 tps = 1000 + 响应时间 = 1s

假设并发理解为 TPS 的话,可能花 30 个线程就可以达到 1000tps 执行 60 秒,结果也能产出 60000 条数据

而从你这句话来倒推,30 个线程能达到 1000 tps ,意味着平均每个线程每秒得产生 33 tps,意味着接口的响应时间必须控制在 1/33(约为 0.03)秒左右。要满足这个场景,性能需要达到 tps = 1000 + 响应时间 = 0.03s

所以,加上响应时间这个指标后,你能明确看出来,这两个场景下对服务端的性能要求其实差了 33 倍了吧?

  • 至于为啥大家会喜欢用线程数,我觉得里面有一些历史因素。

以前 LR 类似 JMeter 线程数的东西叫做 virtualUser(虚拟用户),意思是这个就是虚拟有多少个用户在使用。同时为了让这些用户表现更符合实际情况,还会有需要在每个操作之间加入 thinkTime(思考时间,实际就是固定的等待时长)。所以我只需要评估高峰期大概系统会有多少个用户来用,正常用户习惯每次操作之间间隔多久,就可以把这个场景直接输入到性能测试工具里,直接作为性能场景使用了。

但随着时间推移,这个思考时间越来越少人用或者考虑,因为不管设定多少都很难靠谱,而且思考时间差 1 秒,实际发起的压力就会有很大差异。但虚拟用户转变为线程数继续留在了 Jmeter 里,所以大家会习惯继续这么称呼,毕竟老板和产品更能听懂 “并发用户数” 这类词。但实际上只要稍微想细一点,就会发现不精确,因为这个场景下,线程和实际用户的核心差异是,线程得到响应后会立即再次发起请求,但实际用户谁有空没事做会一直不间断给你发请求呢。

因此,一个合格的性能测试工程师,应该能做好翻译工作,把老板和产品的想法,转换为专业的性能指标,应用到性能测试里。

墨妖 回复

一般高并发(线程)才能达到高 tps

这个结论和我日常认知差异有点大,建议你试试用 10 个线程去测试某个逻辑比较简单的接口,然后换 100 个线程再测一次,对比看下 10 个线程下的 tps ,和 100 线程下的 tps ,差异会不会很大?

wchzs #14 · 2022年04月12日 Author

翻到一篇阿里云大佬写的,现在性能这块应该是分成了两个派系,一派是并发,一派是 TPS,但是两个流派都能通过分析和调优解决问题。

https://developer.aliyun.com/article/709950

看了后思路突然打开了,既然线程数和 TPS 都能解决问题的话,那其实配合团队目前的水平更改测试方式才是正确的。

wchzs #15 · 2022年04月12日 Author
陈恒捷 回复

我目前也是这样理解的,而且实际压测过程中拿着 TPS 和响应时间找开发运维进行调优的时候他们也比较有方向,调优的目的只有一个,就是减少响应时间增加 TPS。但现在换了个团队之后概念这块都要重头来,并发这块统一口径挺难的,要么争论要么加入。

wchzs 回复

一般不是业务和产品喜欢用并发用户数 +rt,开发运维喜欢用 tps+rt 吗?你意思是现在开发和运维也喜欢用并发用户数了?

wchzs #17 · 2022年04月13日 Author
陈恒捷 回复

目前待的这个团队,性能指标只有并发用户数,只要不报错就继续加线程😅 ,开发可能为了省事也同意这个指标,昨天特地为这个争论了一下,没啥作用。

wchzs 回复

如果实在无法改变,那就先保持一致吧。

我一般的做法是,把产品的性能需求想办法转换为 tps+rt 目标指标,然后再去拿这个来和开发运维沟通以及出报告。一般其他角色只要觉得你的转换思路听起来是靠谱的,那他们也不会说你非得怎么怎么样,毕竟这个不是他们专业范畴,一讲深他们其实也就听不懂了。

陈恒捷 回复

交流一下,这是一个简单的查询接口 10 并发和 50 并发下的结果,理想情况下,响应时间应该一样,而 tps 变成 5 倍,实际上响应时间些许增加,这个跟我发送速率没有达到 5 倍也有关

在服务端能力没有到达拐点之前,并发增加,响应时间应该几乎不变,而 tps 也会增加,或者说不增加并发是没法测到 tps 的最大值,这有什么问题请指教

墨妖 回复

不好意思,确实我之前逻辑不够严谨。在服务端没有达到满负荷(即服务端每个处理线程都在工作中没有闲置,也是我们俗称的性能拐点)时,确实是压测工具的线程数增加,响应时间不变,tps 增加。

我其实核心不认同的应该是 线程数=并发 这个观点。我对这个观点的理解是:针对正文里的 登录接口能够承受秒级 1000 并发 ,就应该用假设 1 里面的 1000 个线程去发起压力,并要求响应时间达标。

在我的经验里,一般在线程数在比目标 tps 低不少的时候,系统就可以达到目标 tps 了。真要用和用户数一样的线程数去压且不考虑思考时间(现在越来越少人用这个了),容易给到过大的压力。

陈恒捷 回复

针对正文里的 登录接口能够承受秒级 1000 并发 ,就应该用假设 1 里面的 1000 个线程去发起压力,并要求响应时间达标。

我也是这么理解,没毛病

  • QPS(Queries Per Second):每秒的用户访问量(也有叫 RPS 的)
  • TPS(Transcations Per Second):每秒的 Transcations 数量(Transcation 是一个抽象概念所以不好用中文直翻,可以类比事务,个人理解是业务单个分支的完整流程,而完整的业务流程可能是多个分支一同完成)

QPS is basically similar to TPS, but the difference is that a single visit to a page forms a TPS; however, a page request may generate multiple requests to the server, which can be included in the “QPS”.

上述出自链接

在搞明白概念的区别之后,再来看术语的应用场景。性能测试关注点是性能上,所以只要把性能解释清楚就好,在不同的公司,无论对与错,无论术语用得专不专业,只要大家都知道在说同一个东西其实也还好。


回到问题上,性能测试关注的是性能,而制造性能压力一般来源于并发访问量和能使用的资源,所以我们要描述压力大小,就相当于要描述并发量以及提供给系统的资源量。

TPS 和 QPS 对比,按照老外的解释,TPS 是一个更内部更拆解的概念,在业务足够简单的情况下它可以跟 QPS 等价;QPS 是更面向用户的概念,它把整个系统看成整体,不管你系统内部怎么运作,现在每秒多一个访问过来那就是 QPS 加一,更直观更好理解也更容易统计,所以我推荐用 QPS 来表示并发或者压力程度,当然单纯说 QPS 是没用的,还要加上请求正常响应比例等条件的约束才有实际分析意义,就不展开扯了。

还有一个很重要的点,要区分好线程数和 QPS 两个概念,个人感觉之所以会把线程数等价于 QPS,可能是习惯将 Jmeter 世界里的概念搬到其他场景来。因为 Jmeter 实现发压是基于多线程模型,不严谨地说就是一个线程发一个请求,很古老的 I/O 模型,在当时可能是很好的方案,但现在看来会有局限。对比与 Locust、Gatling、K6 等更新一代的压测工具,使用更高效的 I/O 模型更有利于榨干发压机的性能,这个时候就再也不是一个线程等价一个请求。所以,不能用线程数来代表并发,而是用该以实际发了多少请求给服务器来统计并发这篇文章写得很好建议阅读。

陈恒捷 回复


有点不太理解, 为什么要用假设 1 中的 1000 线程呢.
假如: 登录接口的响应时间平均 0.2 秒. 那么 1000 个线程会造成 5000/s 的 TPS 吧 (服务器没达到瓶颈的前提下). 而这个测试的需求: 秒级 1000 用户并发. 理解为 1000/s TPS 去测的话, 200 个线程数就够了.

前段时间做过一些系统的性能测试, 如果将常说的 1000 并发理解为 1000 线程话, 如果响应时间低于 1s 的时候, 很容易造成大于 1000/s 的 TPS 压力, 导致服务器过载.

所以现在我们的思路就是当开发提到某某接口预计要能支持 1000 并发的时候, 如果响应时间要求低于 1s, 我们往往会转化为 1000TPS 的目标去测. 而如果响应时间要求低于 2s, 那么就按照 1000/2s 的 TPS 去测. 这样出的结果, 也比较容易和运维抓到的客户当前的请求量相结合匹配.

所以, 是我理解错了吗😹

这就让我 想到一个问题 一个性能需求是这样的 老板发话 我们的系统要支持 1000 的并发
这个 1000 的并发其实 不谈 rt 是真的没啥意义的
如果你真的用 1000 个线程去压 合适吗? 1000 个线程产生的压力有多大 服务器能响应得过来吗
但是你再细化下需求 1000 的并发 而且每次请求的 rt 要在 500ms 以内(服务器资源、中间件等等先不谈) 不就清晰了?
你可以用 jmeter 固定 rps 1000 的方式去压 观察 rt 是否能保持在 500ms 以内

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册