mirror of
https://github.com/cheetahlou/CategoryResourceRepost.git
synced 2025-11-16 22:23:45 +08:00
mod
This commit is contained in:
176
极客时间专栏/性能测试实战30讲/第一模块:性能测试基础篇/01丨性能综述:性能测试的概念到底是什么?.md
Normal file
176
极客时间专栏/性能测试实战30讲/第一模块:性能测试基础篇/01丨性能综述:性能测试的概念到底是什么?.md
Normal file
@@ -0,0 +1,176 @@
|
||||
<audio id="audio" title="01丨性能综述:性能测试的概念到底是什么?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/91/ff/91a975b19bfa9be04c75bd631deb4aff.mp3"></audio>
|
||||
|
||||
在性能测试行业中,长久以来,都存在几个关键的概念误差。在我从业性能测试十几年的经历中,也看到过书籍或网上传播着各种性能测试的概念、方法论等,但是究其本质,再对应到具体的项目工作中,我发现这些概念以及方法论实在没有指导的价值,并且有些概念的产出,也没有确凿的证据来源。
|
||||
|
||||
所以在今天,专栏正式更新的第一天,我希望能把这些内容做些梳理,同时这些梳理的内容也会对应到后续的篇幅之中,以便保持理念的一致性。
|
||||
|
||||
## 性能测试概念
|
||||
|
||||
我们经常看到的性能测试概念,有人或称之为性能策略,或称之为性能方法,或称之为性能场景分类,大概可以看到性能测试、负载测试、压力测试、强度测试等一堆专有名词的解释。
|
||||
|
||||
针对这些概念,我不知道你看到的时候会不会像我的感觉一样:乱!一个小小的性能测试,就延伸出了这么多的概念,并且概念之间的界限又非常模糊。
|
||||
|
||||
就拿“压力测试”、“容量测试”和“极限测试”这三个概念来说吧。
|
||||
|
||||
网上针对这三个名词的解释是这样的:
|
||||
|
||||
>
|
||||
<p>**压力测试**<br>
|
||||
压力测试是评估系统处于或超过预期负载时系统的运行情况。压力测试的关注点在于系统在峰值负载或超出最大载荷情况下的处理能力。在压力级别逐渐增加时,系统性能应该按照预期缓慢下降,但是不应该崩溃。压力测试还可以发现系统崩溃的临界点,从而发现系统中的薄弱环节。</p>
|
||||
|
||||
|
||||
>
|
||||
<p>**容量测试**<br>
|
||||
确定系统可处理同时在线的最大用户数,使系统承受超额的数据容量来发现它是否能够正确处理。</p>
|
||||
|
||||
|
||||
>
|
||||
<p>**极限测试**<br>
|
||||
在过量用户下的负载测试。</p>
|
||||
|
||||
|
||||
恕我直言,这三个概念,对我这个从事性能测试十几年的老鸟来说,都看不出来有啥区别。
|
||||
|
||||
也许你会说,你看那里不是说了吗?
|
||||
|
||||
“压力测试是在超过预期负载时系统的运行情况”,“容量测试是使系统承受超额的数据容量来发现它是否能够正确处理”。
|
||||
|
||||
来吧,就算我语文不好,我也认字的,谁能告诉我这两者的区别是什么?除了字不一样。
|
||||
|
||||
如果再抽象一层说一下这些概念,那就是,这些概念都在描述性能测试的不同侧面。而这些侧面本身构不成策略,构不成方法,不能说是概念,也不能说是理论。
|
||||
|
||||
此文一出,肯定会有人说,既然你评价当前的概念混乱,那你有什么好建议呢?作为可能被集体轰炸的话题,既然已经摆上了台面,我还是要冒死给一个自己认为的合理定义:
|
||||
|
||||
>
|
||||
**性能测试针对系统的性能指标,建立性能测试模型,制定性能测试方案,制定监控策略,在场景条件之下执行性能场景,分析判断性能瓶颈并调优,最终得出性能结果来评估系统的性能指标是否满足既定值。**
|
||||
|
||||
|
||||
这是我觉得唯一合理的概念定义,下面我就把这个概念详细解释一下。
|
||||
|
||||
### 性能测试需要有指标
|
||||
|
||||
有人说,我们在做项目的时候,就没有指标,老板只说一句,系统压死为止。听起来很儿戏,但这样的场景不在少数。在我看来,把系统压死也算是一种指标。至于你用什么手段把系统“压死”,那就是实现的问题了。你可以采用很多种手段,告诉老板,这系统还没压就死了! 这也是你的贡献。
|
||||
|
||||
而对“有指标”这个定义来说,理论上合理的,并且应该有的指标是:时间指标、容量指标和资源利用率指标。
|
||||
|
||||
而这里的指标又会有细分,细分的概念又是一团乱。这个话题我们后面再描述。
|
||||
|
||||
### 性能测试需要有模型
|
||||
|
||||
模型是什么?它是真实场景的抽象,可以告诉性能测试人员,业务模型是什么样子。比如说,我们有100种业务,但不是每个业务都需要有并发量,可能只有50个业务有,那就要把这些有并发的业务统计出来,哪个业务并发多,哪个业务并发少,做压力时就要控制好这样的比例。
|
||||
|
||||
这种做法需要的数据通常都是从生产环境中的数据中统计来的,很多在线上不敢直接压测的企业都是这样做的。
|
||||
|
||||
而随着互联网中零售业、云基础架构的全面发展,有些企业直接在线上导流来做性能测试,这种思路上的转变来源于架构的发展及行业的真实需要。但这并不能说明性能测试不需要模型了,因为这个模型已经从生产流量中导过来了。这一点,还是需要你认清的。
|
||||
|
||||
但是对于其他的一些行业,比如银行这类金融机构,线上一个交易都不能错。像上面这样做的难度就太大了。所以这些行业中,仍然需要在测试环境中用业务模型来模拟出生产的流量。
|
||||
|
||||
同时也请你认清一点,现在的全链路压测,并没有像吹嘘得那么神乎其神,很多企业也只是在线上的硬件资源上做压力而已,并不是真正的逻辑链路修改。
|
||||
|
||||
我在工作中经常会被问到,性能流量直接从生产上导的话,是不是就可以不用性能测试人员了?性能测试人员就要被淘汰了?
|
||||
|
||||
这未免太短视了,大家都盯着最新鲜的技术、方法、概念,各层的领导也都有自己的知识偏好,万一做了一个决定,影响了最终的结果,有可能会让很多人跟着受罪。
|
||||
|
||||
我之前带过的一个团队中,开发架构们一开始就规划了特别详细的微服务架构,说这一套非常好。我说这个你们自己决定,我只要在这里面拿到可用的结果就行。结果开发了不到两个月,一个个微服务都被合并了,还得天天加班做系统重构,只留了几大中台组件。这是为什么呢?因为不适用呀。
|
||||
|
||||
同理,性能测试也要选择适合自己系统业务逻辑的方式,用最低的成本、最快的时间来做事情。
|
||||
|
||||
### 性能测试要有方案
|
||||
|
||||
方案规定的内容中有几个关键点,分别是测试环境、测试数据、测试模型、性能指标、压力策略、准入准出和进度风险。基本上有这些内容就够了,这些内容具体的信息还需要精准。
|
||||
|
||||
你可能会说,怎么没有测试计划?我的建议是,用项目管理工具单独画测试计划,比如用Project或OmniPlan之类的工具。这是因为在方案中,写测试计划,基本上只能写一个里程碑,再细化一点,就是在里面再加几个大阶段的条目。但是用项目管理工具做计划就不同了,它不仅可以细分条目,还能跟踪各个工作的动态进度,可以设置前后依赖关系,填入资源和成本以便计算项目偏差。
|
||||
|
||||
### 性能测试中要有监控
|
||||
|
||||
这个部分的监控,要有分层、分段的能力,要有全局监控、定向监控的能力。关于这一点,我将在第三模块详细说明。
|
||||
|
||||
### 性能测试要有预定的条件
|
||||
|
||||
这里的条件包括软硬件环境、测试数据、测试执行策略、压力补偿等内容。要是展开来说,在场景执行之前,这些条件应该是确定的。
|
||||
|
||||
有人说,我们压力中也会动态扩展。没问题,但是动态扩展的条件或者判断条件,也是有确定的策略的,比如说,我们判断CPU使用率达到80%或I/O响应时间达到10ms时,就做动态扩展。这些也是预定的条件。
|
||||
|
||||
关于这一点,在我的工作经历中,经常看到有性能测试工程师,对软硬件资源、测试数据和执行策略分不清楚,甚至都不明白为什么要几分钟加几个线程。在这种情况之下,就不能指望这个场景是有效的了。
|
||||
|
||||
### 性能测试中要有场景
|
||||
|
||||
可以说,“性能场景”这个词在性能测试中占据着举足轻重的地位,只是我们很多人都不理解“场景”应该如何定义。场景来源于英文的scenario,对性能场景中的“场景”比较正宗的描述是:在既定的环境(包括动态扩展等策略)、既定的数据(包括场景执行中的数据变化)、既定的执行策略、既定的监控之下,执行性能脚本,同时观察系统各层级的性能状态参数变化,并实时判断分析场景是否符合预期。
|
||||
|
||||
这才是真正的场景全貌。
|
||||
|
||||
性能场景也要有分类,在我有限的工作经验中,性能场景从来都没有超出过这几个分类。
|
||||
|
||||
1. 基准性能场景:这里要做的是单交易的容量,为混合容量做准备(不要跟我说上几个线程跑三五遍脚本叫基准测试,在我看来,那只是场景执行之前的预执行,用来确定有没有基本的脚本和场景设计问题,不能称之为一个分类)。
|
||||
1. 容量性能场景:这一环节必然是最核心的性能执行部分。根据业务复杂度的不同,这部分的场景会设计出很多个,在概念部分就不细展开了,我会在后面的文章中详细说明。
|
||||
1. 稳定性性能场景:稳定性测试必然是性能场景的一个分类。只是现在在实际的项目中,稳定性测试基本没和生产一致过。在稳定性测试中,显然最核心的元素是时间(业务模型已经在容量场景中确定了),而时间的设置应该来自于运维周期,而不是来自于老板、产品和架构等这些人的心理安全感。
|
||||
1. 异常性能场景:要做异常性能场景,前提就是要有压力。在压力流量之下,模拟异常。这个异常的定义是很宽泛的,在下一篇文章里,我们再细说。
|
||||
|
||||
很多性能测试工程师,都把场景叫成了测试用例。如果只是叫法不同,我觉得倒是可以接受,关键是内容也出现了很大的偏差,这个偏差就是,把用例限定在了描述测试脚本和测试数据上,并没有描述需要实时的判断和动态的分析。这就严重影响了下一个概念:性能结果。
|
||||
|
||||
### 性能测试中要有分析调优
|
||||
|
||||
一直以来,需不需要在性能测试项目中调优,或者说是不是性能测试工程师做调优,人们有不同的争论。
|
||||
|
||||
从性能市场的整体状态来看,在性能测试工程师中,可以做瓶颈判断、性能分析、优化的人并不多,所以很多其他职位上的人对性能测试的定位也就是性能验证,并不包括调优的部分。于是有很多性能项目都定义在一两周之内。这类项目基本上也就是个性能验证,并不能称之为完整的性能项目。而加入了调优部分之后,性能项目就会变得复杂。对于大部分团队来说,分析瓶颈都可能需要很长时间,这里会涉及到相关性分析、趋势分析、证据链查找等等手段。
|
||||
|
||||
所以,就要不要进行调优,我做了如下划分。
|
||||
|
||||
对性能项目分为如下几类。
|
||||
|
||||
1. **新系统性能测试类**:这样的项目一般都会要求测试出系统的最大容量,不然上线心里没底。
|
||||
1. **旧系统新版本性能测试类**:这样的项目一般都是和旧版本对比,只要性能不下降就可以根据历史数据推算容量,对调优要求一般都不大。
|
||||
1. **新系统性能测试优化类**:这类的系统不仅要测试出最大容量,还要求调优到最好。
|
||||
|
||||
对性能团队的职责定位有如下几种。
|
||||
|
||||
1. **性能验证**:针对给定的指标,只做性能验证。第三方测试机构基本上都是这样做的。
|
||||
1. **性能测试**:针对给定的系统,做全面的性能测试,可以得到系统最大容量,但不涉及到调优。
|
||||
1. **性能测试+分析调优**:针对给定的系统,做全面的性能测试,同时将系统调优到最优状态。
|
||||
|
||||
当只能做性能验证的团队遇到旧系统新版本性能测试类和新系统性能测试优化类项目,那就会很吃力,这样的团队只能做新系统性能测试类项目。
|
||||
|
||||
当做性能测试的团队,遇到需要新系统性能测试优化类项目,照样很吃力。这样的团队能做前两种项目。
|
||||
|
||||
只有第三个团队才能做第三种项目。
|
||||
|
||||
### 性能测试肯定要有结果报告
|
||||
|
||||
性能结果如何来定义呢?有了前面监控的定义,有了场景执行的过程,产生的数据就要整理到结果报告中了。这个文档工作也是很重要的,是体现性能团队是否专业的一个重要方面。并不是整理一个Word,美化一下格式就可以了。测试报告是需要汇报或者归档的。
|
||||
|
||||
如果是内部项目,测试报告可能就是一个表格,发个邮件就完整了,另外归档也是必须的。而对一些有甲乙方的项目,就需要汇报了。
|
||||
|
||||
那么,如何汇报呢?
|
||||
|
||||
我们要知道,大部分老板或者上司关心的是测试的结果,而不是用了多少人,花了多少时间这些没有意义的数字。我们更应该在报告中写上调优前后的TPS、响应时间以及资源对比图。
|
||||
|
||||
有了上面的的解析,相信你对性能测试的定义有了明确的感觉了。这个定义其实就是描述了性能测试中要做的事情。
|
||||
|
||||
当然,也许会有人跳出来说,你这个说得太重了,不够敏捷。现在不都用DevOps了吗?还要按这个流程来走一遍吗?
|
||||
|
||||
显然有这种说法的人,没有理解我要说的主旨。以上的内容是针对一个完整的项目,或系统或公司的系统演进。对于一些半路就跟着版本和新需求一轮轮迭代做下去的人的处境会不同,因为这样的人只看到了当前的部分,而不是整个过程。
|
||||
|
||||
并且这个过程也是不断在迭代演进的。
|
||||
|
||||
不管是敏捷开发过程还是DevOps,你可以一条条去仔细分析下项目中的各个环节(我说的是整个项目从无到有),都不会跳出以上定义,如果有的话,请随时联系我,我好改定义。:)
|
||||
|
||||
通过图示最后总结一下性能测试的概念:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/fe/69/fe7b646c360f1ef016959aff13050969.jpg" alt=""><br>
|
||||
有了这个图示之后,就比较清晰了。
|
||||
|
||||
所以,前面所说的压力测试、容量测试、负载测试等等,在实际的项目实施过程中,都不具备全局的指导价值。我个人认为,你应该在性能领域中抛弃这些看似非常有道理实则毫无价值的概念。
|
||||
|
||||
## 总结
|
||||
|
||||
今天的内容我只讲了一点,那就是性能测试的概念。请不要再使用像性能测试、负载测试、容量测试这样的词来概括性能执行策略,这是对实施过程没有任何指导价值的。
|
||||
|
||||
在性能测试的概念中,性能指标、性能模型、性能场景、性能监控、性能实施、性能报告,这些既是概念中的关键词,也可以说是性能测试的方法和流程。
|
||||
|
||||
而这些概念我们在实际的工作中,都是非常重要的。因为它们要抹平沟通的误解。让不同层级,不同角色的人,可以在同样的知识背景下沟通,也可以让做事情的人有清晰的逻辑思路,同时对同行间的交流,也有正向的促进作用。
|
||||
|
||||
## 思考题
|
||||
|
||||
最后给你留两道思考题吧,我为什么不推荐使用性能测试、负载测试、容量测试这样的词来概括性能执行策略呢?以及,为什么性能测试中要有监控和分析?
|
||||
|
||||
欢迎你在评论区写下你的思考,也欢迎把这篇文章分享给你的朋友或者同事,一起交流一下。
|
||||
84
极客时间专栏/性能测试实战30讲/第一模块:性能测试基础篇/02丨性能综述:TPS和响应时间之间是什么关系?.md
Normal file
84
极客时间专栏/性能测试实战30讲/第一模块:性能测试基础篇/02丨性能综述:TPS和响应时间之间是什么关系?.md
Normal file
@@ -0,0 +1,84 @@
|
||||
<audio id="audio" title="02丨性能综述:TPS和响应时间之间是什么关系?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/4a/ab/4ab3bffd7a9959e6b3e08c95b667dfab.mp3"></audio>
|
||||
|
||||
我们在上一篇文章中讲了性能测试的概念,肯定会有人觉得,那些概念很重要,怎么能轻易抹杀呢?那么,在今天的文章中,我们就来扒一扒性能场景,看看概念与实际之间的差别。
|
||||
|
||||
前面我们说了性能要有场景,也说了性能场景要有基准性能场景、容量性能场景、稳定性性能场景、异常性能场景。在我有限的十几年性能生涯中,从来没有见过有一个性能场景可以超出这几个分类。下面我将对前面说到的概念进行一一对应。
|
||||
|
||||
学习性能的人,一定看吐过一张图,现在让你再吐一次。如下:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/36/7d/36ee34ee92b75fd17d5314d74453367d.png" alt=""><br>
|
||||
在这个图中,定义了三条曲线、三个区域、两个点以及三个状态描述。
|
||||
|
||||
1. 三条曲线:吞吐量的曲线(紫色)、使用率/用户数曲线(绿色)、响应时间曲线(深蓝色)。
|
||||
1. 三个区域:轻负载区(Light Load)、重负载区(Heavy Load)、塌陷区(Buckle Zone)。
|
||||
1. 两个点:最优并发用户数(The Optimum Number of Concurrent Users)、最大并发用户数(The Maximum Number of Concurrent Users)。
|
||||
1. 三个状态描述:资源饱和(Resource Saturated)、吞吐下降(Throughput Falling)、用户受影响(End Users Effected)。
|
||||
|
||||
我在很多地方,都看到了对这张图的引用。应该说,做为一个示意图,它真的非常经典,的确描述出了一个基本的状态。但是,示意图也只能用来做示意图,在具体的项目中,我们仍然要有自己明确的判断。
|
||||
|
||||
我们要知道,这个图中有一些地方可能与实际存在误差。
|
||||
|
||||
首先,很多时候,重负载区的资源饱和,和TPS达到最大值之间都不是在同样的并发用户数之下的。比如说,当CPU资源使用率达到100%之后,随着压力的增加,队列慢慢变长,但是由于用户数增加的幅度会超过队列长度,所以TPS仍然会增加,也就是说资源使用率达到饱和之后还有一段时间TPS才会达到上限。
|
||||
|
||||
大部分情况下,响应时间的曲线都不会像图中画得这样陡峭,并且也不一定是在塌陷区突然上升,更可能的是在重负载区突然上升。
|
||||
|
||||
另外,吞吐量曲线不一定会出现下降的情况,在有些控制较好的系统中会维持水平。曾经在一个项目中,因为TPS维持水平,并且用户数和响应时间一直都在增加,由于响应时间太快,一直没有超时。我跟我团队那个做压力的兄弟争论了三个小时,我告诉他接着压下去已经没有意义,就是在等超时而已。他倔强地说,由于没有报错,时间还在可控范围,所以要一直加下去。关于这一点争论,我在后续的文章中可能还会提及。
|
||||
|
||||
最优并发数这个点,通常只是一种感觉,并没有绝对的数据用来证明。在生产运维的过程中,其实我们大部分人都会更为谨慎,不会定这个点为最优并发,而是更靠前一些。
|
||||
|
||||
最大并发数这个点,就完全没有道理了,性能都已经衰减了,最大并发数肯定是在更前的位置呀。这里就涉及到了一个误区,压力工具中的最大用户数或线程数和TPS之间的关系。在具体的项目实施中,有经验的性能测试人员,都会更关心服务端能处理的请求数即TPS,而不是压力工具中的线程数。
|
||||
|
||||
这张图没有考虑到锁或线程等配置不合理的场景,而这类场景又比较常见。也就是我们说的,TPS上不去,资源用不上。所以这个图默认了一个前提,只要线程能用得上,资源就会蹭蹭往上涨。
|
||||
|
||||
这张图呢,本来只是一个示意,用以说明一些关系。但是后来在性能行业中,有很多没有完全理解此图的人将它做为很有道理的“典范”给一些人讲,从而引起了越来越多的误解。
|
||||
|
||||
此图最早的出处是2005年Quest Software的一个PSO Consultant写的一个白皮书[《Performance Testing Methodology》](http://hosteddocs.ittoolbox.com/questnolg22106java.pdf)。在18页论述了这张图,原文摘录一段如下:
|
||||
|
||||
>
|
||||
You can see that as user load increases, response time increases slowly and resource utilization increases almost linearly. This is because the more work you are asking your application to do, the more resources it needs. Once the resource utilization is close to 100 percent, however, an interesting thing happens – response degrades with an exponential curve. This point in the capacity assessment is referred to as the saturation point. The saturation point is the point where all performance criteria are abandoned and utter panic ensues. Your goal in performing a capacity assessment is to ensure that you know where this point is and that you will never reach it. You will tune the system or add additional hardware well before this load occurs.
|
||||
|
||||
|
||||
按照这段描述,这个人只是随着感觉在描述一种现象,除此无它。比如说,The saturation point is the point where all performance criteria are abandoned and utter panic ensues.在我的工作经验中,其实在saturation point之前,性能指标就已经可以显示出问题了,并且已经非常panic了,而我们之所以接着再加压力是为了让指标显示得更为明显,以便做出正确的判断。而调优实际上是控制系统在饱和点之前,这里有一个水位的问题,控制容量到什么样的水位才是性能测试与分析的目标。
|
||||
|
||||
我们简化出另一个图形,以说明更直接一点的关系。如下所示:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/c0/34/c0575730fe2d14842aba066bc8786734.png" alt=""><br>
|
||||
上图中蓝线表示TPS,黄色表示响应时间。
|
||||
|
||||
在TPS增加的过程中,响应时间一开始会处在较低的状态,也就是在A点之前。接着响应时间开始有些增加,直到业务可以承受的时间点B,这时TPS仍然有增长的空间。再接着增加压力,达到C点时,达到最大TPS。我们再接着增加压力,响应时间接着增加,但TPS会有下降(请注意,这里并不是必然的,有些系统在队列上处理得很好,会保持稳定的TPS,然后多出来的请求都被友好拒绝)。
|
||||
|
||||
最后,响应时间过长,达到了超时的程度。
|
||||
|
||||
在我的工作中,这样的逻辑关系更符合真实的场景。我不希望在这个关系中描述资源的情况,因为会让人感觉太乱了。
|
||||
|
||||
为什么要把上面描述得如此精细?这是有些人将第一张图中的Light load对应为性能测试,Heavy Load对应为负载测试,Buckle Zone对应为压力测试……还有很多的对应关系。
|
||||
|
||||
事实上,这是不合理的。
|
||||
|
||||
下面我将用场景的定义来替换这些混乱的概念。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/55/b1/55168e3443446e5866c85853f0e71ab1.jpg" alt="">
|
||||
|
||||
为什么我要如此划分?因为在具体场景的操作层面,只有场景中的配置才是具体可操作的。而通常大家认为的性能测试、负载测试、压力测试在操作的层面,只有压力工具中线程数的区别,其他的都在资源分析的层面,而分析在很多人的眼中,都不算测试。
|
||||
|
||||
拿配置测试和递增测试举例吧。
|
||||
|
||||
在性能中,我们有非常多的配置,像JVM参数、OS参数、DB参数、网络参数、容器参数等等。如果我们把测试这些配置参数,称为”配置测试“,我觉得未免过于狭隘了。因为对于配置参数来说,这只是做一个简单的变更,而性能场景其实没有任何变化呀。配置更改前后,会用同样的性能场景来判断效果,最多再增加一些前端的压力,实际的场景并没有任何变化,所以,我觉得它不配做为一个单独的分类。
|
||||
|
||||
再比如递增测试,在性能中,基准性能场景也好,容量性能场景也好,哪个是不需要递增的呢?我知道现在市场上经常有测试工程师,直接就上了几百几千线程做压力(请你不要告诉我这是个正常的场景,鉴于我的精神有限,承受不了这样的压力)。除了秒杀场景,同时上所有线程的场景,我还没有见到过。在一般的性能场景中,递增都是必不可少的过程。同时,递增的过程,也要是连续的,而不是100线程、200线程、300线程这样断开执行场景,这样是不合理的。关于这一点,我们将在很多地方着重强调。所以我觉得递增也不配做一个单独的分类。
|
||||
|
||||
其他的概念,就不一一批驳了。其实在性能测试中,在实际的项目实施中,我们并不需要这么多概念,这些杂七杂八的概念也并没有对性能测试领域的发展起到什么推进作用。要说云计算、AI、大数据这些概念,它们本身在引导着一个方向。
|
||||
|
||||
而性能测试中被定为“测试”,本身就处在软件生存周期的弱势环节,当前的市场发展也并不好。还被这些概念冲乱了本来应该有的逻辑的思路,实在是得不偿失。
|
||||
|
||||
## 总结
|
||||
|
||||
总之,在具体的性能项目中,性能场景是一个非常核心的概念。因为它会包括压力发起策略、业务模型、监控模型、性能数据(性能中的数据,我一直都不把它称之为模型,因为在数据层面,测试并没有做过什么抽象的动作,只是使用)、软硬件环境、分析模型等。
|
||||
|
||||
有了清晰的、有逻辑的场景概念之后,在后面的篇幅当中,我们将从场景的各个角度去拆解。在本专栏中,我们将保持理念的连贯性,以示我不变的职业初心。
|
||||
|
||||
## 思考题
|
||||
|
||||
如果你理解了今天的内容,不妨说说为什么说现在市场上的概念对性能项目的实施并没有太大的价值?其次,性能场景为什么要连续?而不是断开?
|
||||
|
||||
欢迎你在评论区写下你的思考,也欢迎把这篇文章分享给你的朋友或者同事,一起交流一下。
|
||||
@@ -0,0 +1,259 @@
|
||||
<audio id="audio" title="03丨性能综述:怎么理解TPS、QPS、RT、吞吐量这些性能指标?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/14/e9/140eed7669a4c664710c59075fae4de9.mp3"></audio>
|
||||
|
||||
在上一篇文章中,我们讲述了性能场景,下面就要说性能需求指标了。
|
||||
|
||||
通常我们都从两个层面定义性能场景的需求指标:业务指标和技术指标。
|
||||
|
||||
这两个层面需要有映射关系,技术指标不能脱离业务指标。一旦脱离,你会发现你能回答“一个系统在多少响应时间之下能支持多少TPS”这样的问题,但是回答不了“业务状态是什么”的问题。
|
||||
|
||||
举例来说,如果一个系统要支持1000万人在线,可能你能测试出来的结果是系统能支持1万TPS,可是如果问你,1000万人在线会不会有问题?这估计就很难回答了。
|
||||
|
||||
我在这里画一张示意图以便你理解业务指标和性能指标之间的关系。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/1b/c2/1bb1222c53e8b16414458a8572e786c2.png" alt="">
|
||||
|
||||
这个示意显然不够详细,但也能说明关系了。所有的技术指标都是在有业务场景的前提下制定的,而技术指标和业务指标之间也要有详细的换算过程。这样一来,技术指标就不会是一块飞地。同时,在回答了技术指标是否满足的同时,也能回答是否可以满足业务指标。
|
||||
|
||||
有了这样的关联关系,下面我们看一下性能测试行业常用的性能指标表示法。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/53/83/533fa609f8607dbd65878fb52ef87183.jpg" alt="">
|
||||
|
||||
我将现在网上能看到的性能指标做了罗列,其中不包括资源的指标。因为资源类的比较具体,并且理解误差并不大,但业务类的差别就比较大了。
|
||||
|
||||
## 对这些性能指标都有哪些误解
|
||||
|
||||
我记得我还年轻的时候,还没有QPS、RPS、CPS这样的概念,只有TPS。那个时候,天总是那么蓝,时间总是那么慢,“你锁了人家就懂了”。
|
||||
|
||||
QPS一开始是用来描述MySQL中SQL每秒执行数Query Per Second,所有的SQL都被称为Query。后来,由于一些文章的转来转去,QPS被慢慢地移到了压力工具中,用来描述吞吐量,于是这里就有些误解,QPS和TPS到底是什么关系呢?
|
||||
|
||||
RPS指的是每秒请求数。这个概念字面意思倒是容易理解,但是有个容易误解的地方就是,它指的到底是哪个层面的Request?如果说HTTP Request,那么和Hits Per Second又有什么关系呢?
|
||||
|
||||
HPS,这也是个在字面意思上容易理解的概念。只是Hit是什么?有人将它和HTTP Request等价,有人将它和用户点击次数等价。
|
||||
|
||||
CPS,用的人倒是比较少,在性能行业中引起的误解范围并不大。同时还有喜欢用CPM(Calls Per Minute,每分钟调用数)的。这两个指标通常用来描述Service层的单位时间内的被其他服务调用的次数,这也是为什么在性能行业中误解不大的原因,因为性能测试的人看Service层东西的次数并不多。
|
||||
|
||||
为了区分这些概念,我们先说一下TPS(Transactions Per Second)。我们都知道TPS是性能领域中一个关键的性能指标概念,它用来描述每秒事务数。我们也知道TPS在不同的行业、不同的业务中定义的粒度都是不同的。所以不管你在哪里用TPS,一定要有一个前提,就是**所有相关的人都要知道你的T是如何定义的**。
|
||||
|
||||
经常有人问,TPS应该如何定义?这个实在是没有具体的“法律规定”,那就意味着,你想怎么定就怎么定。
|
||||
|
||||
通常情况下,我们会根据场景的目的来定义TPS的粒度。如果是接口层性能测试,T可以直接定义为接口级;如果业务级性能测试,T可以直接定义为每个业务步骤和完整的业务流。
|
||||
|
||||
我们用一个示意图来说明一下。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/d2/8d/d2093240be6f4151002d8019cabfac8d.png" alt=""><br>
|
||||
如果我们要单独测试接口1、2、3,那T就是接口级的;如果我们要从用户的角度来下一个订单,那1、2、3应该在一个T中,这就是业务级的了。
|
||||
|
||||
当然,这时我们还要分析系统是如何设计的。通常情况下,积分我们都会异步,而库存不能异步哇。所以这个业务,你可以看成只有1、2两个接口,但是在做这样的业务级压力时,3接口也是必须要监控分析的。
|
||||
|
||||
所以,性能中TPS中T的定义取决于场景的目标和T的作用。一般我们都会这样来定事务。
|
||||
|
||||
<li>接口级脚本:<br>
|
||||
——事务start(接口1)<br>
|
||||
接口1脚本<br>
|
||||
——事务end(接口1)<br>
|
||||
——事务start(接口2)<br>
|
||||
接口2脚本<br>
|
||||
——事务end(接口2)<br>
|
||||
——事务start(接口3)<br>
|
||||
接口3脚本<br>
|
||||
——事务end(接口3)</li>
|
||||
<li>业务级接口层脚本(就是用接口拼接出一个完整的业务流):<br>
|
||||
——事务start(业务A)<br>
|
||||
接口1脚本 - 接口2(同步调用)<br>
|
||||
接口1脚本 - 接口3(异步调用)<br>
|
||||
——事务end(业务A)</li>
|
||||
<li>用户级脚本<br>
|
||||
——事务start(业务A)<br>
|
||||
点击0 - 接口1脚本 - 接口2(同步调用)<br>
|
||||
点击0 - 接口1脚本 - 接口3(异步调用)<br>
|
||||
——事务end(业务A)</li>
|
||||
|
||||
你要创建什么级别的事务,完全取决于测试的目的是什么。
|
||||
|
||||
一般情况下,我们会按从上到下的顺序一一地来测试,这样路径清晰地执行是容易定位问题的。
|
||||
|
||||
## 重新理解那些性能指标概念
|
||||
|
||||
搞清楚了TPS的T是什么,下面就要说什么是TPS了。字面意思非常容易理解,就是:**每秒事务数**。
|
||||
|
||||
在性能测试过程中,TPS之所以重要,是因为它可以反应出一个系统的处理能力。我在很多场景中都说过,事务就是统计了一段脚本的执行时间,并没有什么特别的含义。而现在又多加了其他的几个概念。
|
||||
|
||||
首先是QPS,如果它描述的是数据库中的Query Per Second,从上面的示意图中来看,其实描述的是服务后面接的数据库中SQL的每秒执行条数。如果描述的是前端的每秒查询数,那就不包括插入、更新、删除操作了。显然这样的指标用来描述系统整体的性能是不够全面的。所以不建议用QPS来描述系统整体的性能,以免产生误解。
|
||||
|
||||
RPS(Request per second),每秒请求数。看似简单的理解,但是对于请求数来说,要看是在哪个层面看到的请求,因为请求这个词,实在是太泛了。我们把上面的图做一点点变化来描述一下请求数。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/6d/9c/6d260efd23e2ea7e861070cd15e83e9c.png" alt=""><br>
|
||||
如果一个用户点击了一次,发出来3个HTTP Request,调用了2次订单服务,调用了2次库存服务,调用了1次积分服务,那么这个Request该如何计算?如果你是算GDP的专家,我觉得可能会是:3+2+2+1=8(次)。而在具体的项目中,我们会单独描述每个服务,以便做性能统计。如果要描述整体,最多算是有3个RPS。如果从HTTP协议的角度去理解,那么HTTP Request算是一个比较准确的描述了,但它本身的定义并没有包含业务。如果赋予它业务的含义,那么用它来描述性能也是可以的。
|
||||
|
||||
HPS(Hits Per Second),每秒点击数。Hit一般在性能测试中,都用来描述HTTP Request。但是,也有一些人用它描述真正的客户在界面上的点击次数。关于这一点,就只有在具体的项目中才能规定得具体一些。当它描述HTTP Request时,如果RPS也在描述HTTP Request,那这两个概念就完全一样了。
|
||||
|
||||
CPS/CPM:Calls Per Second/ Calls Per Minutes,每秒/每分钟调用次数。这个描述在接口级是经常用到的,比如说上面的订单服务。显然一次客户界面上的点击调用两次。这个比较容易理解。但是,在操作系统级,我们也经常会听到系统调用用call来形容,比如说用strace时,你就会看见Calls这样的列名。
|
||||
|
||||
这些概念本身并没有问题,但是当上面的概念都用来描述一个系统的性能能力的时候,就混乱了。对于这种情况,我觉得有几种处理方式:
|
||||
|
||||
1. 用一个概念统一起来。我觉得直接用TPS就行了,其他的都在各层面加上限制条件来描述。比如说,接口调用1000 Calls/s,这样不会引起混淆。
|
||||
1. 在团队中定义清楚术语的使用层级。
|
||||
1. 如果没有定义使用层级,那只能在说某个概念的时候,加上相应的背景条件。
|
||||
|
||||
所以,当你和同事在沟通性能指标用哪些概念时,应该描述得更具体一些。在一个团队中,应该先有这些术语统一的定义,再来说性能指标是否满足。
|
||||
|
||||
## 响应时间RT
|
||||
|
||||
在性能中,还有一个重要的概念就是响应时间(Response Time)。这个比较容易理解。我们接着用这张示意图说明:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/7b/ac/7b2fb3aa4129a54ddb28d0e70cc551ac.png" alt=""><br>
|
||||
RT = T2-T1。计算方式非常直接简单。但是,我们要知道,这个时间包括了后面一连串的链路。
|
||||
|
||||
响应时间的概念简单至极,但是,响应时间的定位就复杂了。
|
||||
|
||||
性能测试工具都会记录响应时间,但是,都不会给出后端链路到底哪里慢。经常有人问问题就直接说,我的响应时间很慢。问题在哪呢?在这种情况下,只能回答:不知道。
|
||||
|
||||
因为我们要先画架构图,看请求链路,再一层层找下去。比如说这样:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/bd/eb/bd8a2056546c5917290af512be2342eb.png" alt=""><br>
|
||||
在所有服务的进出口上都做记录,然后计算结果就行了。在做网关、总线这样的系统时,基本上都会考虑这个功能。
|
||||
|
||||
而现在,随着技术的发展,链路监控工具和一些Metrics的使用,让这个需求变得简单了不少。比如说这样的展示:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/80/86/80a03dcc4a81d8bdff96546a1fa18186.png" alt="">
|
||||
|
||||
它很直观地显示了,在一个请求链路上,每个节点消耗的时间和请求的持续时间。
|
||||
|
||||
我顺便在这里说一下调优在当前性能项目中的状态。
|
||||
|
||||
对于响应时间来说,时间的拆分定位是性能瓶颈定位分析中非常重要的一节。但是请注意,这个环节并不是性能测试工程师的最后环节。
|
||||
|
||||
在工作中,我经常看到有很多性能测试工程师连时间拆分都不做,只报一个压力工具中看到的响应时间,就给一个通过不通过的结论,丝毫没有定位。
|
||||
|
||||
另外,有一些性能测试工程师,倒是用各种手段分析了时间的消耗点,但是也觉得自己的工作就此结束了,而不做根本原因的分析或协调其他团队来分析。
|
||||
|
||||
当然在不同的企业里,做分析的角色和要求各不相同,所以也要根据实际的企业现状来说。
|
||||
|
||||
在我的观点中,性能只测不调,那就是性能验证的工作,称不上是完整的性能项目。第三方性能测试的机构可以这样做,但是在一个企业内部这样做的话,性能团队的价值肯定就大打折扣了。
|
||||
|
||||
但是现在有很多人都不把性能调优做为性能团队的工作,主要原因有几点:
|
||||
|
||||
1. 性能测试团队的人能力有限做不到;
|
||||
1. 性能调优代价高,耗时长,不值得做。
|
||||
|
||||
在我带的性能项目中,基本上调优的工作都是我的团队主导的。性能团队当然不可能完全没有技术弱点,所以在很多时候都是协调其他团队的人一起来分析瓶颈点。那为什么是我的团队来主导这个分析的过程呢?
|
||||
|
||||
因为每个技术人员对性能瓶颈的定义并不相同,如果不细化到具体的计数器的值是多少才有问题,有误解的可能性就很大。
|
||||
|
||||
曾经我在某零售业大厂做性能咨询的时候,一房间的技术人员,开发、运维、DBA都有,结果性能瓶颈出现了,所有人都说自己的部分是没问题的。于是我一个个问他们是如何判断的,判断的是哪个计数器,值又是多少。结果发现很多人对瓶颈的判断都和我想像的不一样。
|
||||
|
||||
举例来说,DB的CPU使用率达到90%以上,DBA会觉得没有问题,因为都是业务的SQL,并不是DB本身有问题。开发觉得SQL执行时间慢是因为DB有问题,而不是自己写的有问题,因为业务逻辑并没有错,有问题的点应该是DB上索引不合理、配置不合理。
|
||||
|
||||
你看,同样的问题,每个人的看法都有区别。当然也不能排除有些人就是想推诿责任。
|
||||
|
||||
这时怎么办呢?如果你可以把执行计划拿出来,告诉大家,这里应该创建索引,而那里应该修改业务条件,这时就具体了。
|
||||
|
||||
### 压力工具中的线程数和用户数与TPS
|
||||
|
||||
总是有很多人在并发线程数和TPS之间游荡,搞不清两者的关系与区别。这两个概念混淆的点就是,好像线程是真实的用户一样,那并发的线程是多少就描述出了多少真实的用户。
|
||||
|
||||
但是做性能的都会知道,并发线程数在没有模拟真实用户操作的情况下,和真实的用户操作差别非常远。
|
||||
|
||||
在LoadRunner还比较红火的时候,Mercury提出一个BTO的概念,就是业务科技优化。在LoadRunner中也提出”思考时间“的概念,其实在其他的性能工具中是没有“思考时间”这个词的。这个词的提出就是为了性能工具模拟真实用户。
|
||||
|
||||
但是随着性能测试的地位不断下降,以及一些概念和名词不断地被以讹传讹,导致现在很多人都没有明白压力工具中的线程数和用户以及TPS之间是怎样的关系。同样,我们先画一个示意图来说明一下。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/23/2b/23c22b843df28ae9092e76a566077b2b.png" alt=""><br>
|
||||
这里先说明一个前提,上面的一个框中有四个箭头,每个都代表着相同的事务。
|
||||
|
||||
在说这个图之前,我们要先说明“并发”这个概念是靠什么数据来承载的。
|
||||
|
||||
在上面的内容中,我们说了好多的指标,但并发是需要具体的指标来承载的。你可以说,我的并发是1000TPS,或者1000RPS,或者1000HPS,这都随便你去定义。但是在一个具体的项目中,当你说到并发1000这样没有单位的词时,一定要让大家都能理解这是什么。
|
||||
|
||||
在上面这张示意图中,其实压力工具是4个并发线程,由于每个线程都可以在一秒内完成4个事务,所以总的TPS是16。这非常容易理解吧。而在大部分非技术人的脑子里,这样的场景就是并发数是4,而不是16。
|
||||
|
||||
要想解释清楚这个非常困难,我的做法就是,直接告诉别人并发是16就好了,不用关心4个线程这件事。这在我所有项目中几乎都是一样的,一直也没有什么误解。
|
||||
|
||||
那么用户数怎么来定义呢?涉及到用户就会比较麻烦一点。因为用户有了业务含义,所以有些人认为一个系统如果有1万个用户在线,那就应该测试1万的并发线程,这种逻辑实在是不技术。通常,我们会对在线的用户做并发度的分析,在很多业务中,并发度都会低于5%,甚至低于1%。
|
||||
|
||||
拿5%来计算,就是10000用户x5%=500(TPS),注意哦,这里是TPS,而不是并发线程数。如果这时响应时间是100ms,那显然并发线程数是500TPS/(1000ms/100ms)=50(并发线程)。
|
||||
|
||||
通过这样简单的计算逻辑,我们就可以看出来用户数、线程数和TPS之间的关系了。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/72/e0/724b0e330ee9f8a97ac9b8326af370e0.png" alt=""><br>
|
||||
但是!响应时间肯定不会一直都是100ms的嘛。所以通常情况下,上面的这个比例都不会固定,而是随着并发线程数的增加,会出现趋势上的关系。
|
||||
|
||||
所以,在性能分析中,我一直在强调着一个词:**趋势!**
|
||||
|
||||
### 业务模型的28原则是个什么鬼?
|
||||
|
||||
我看到有些文章中写性能测试要按28原则来计算并发用户数。大概的意思就是,如果一天有1000万的用户在使用,系统如果开10个小时的话,在计算并发用户数的时候,就用2小时来计算,即1000万用户在2小时内完成业务。
|
||||
|
||||
我要说的是,这个逻辑在一个特定的业务系统中是没有任何价值的。因为每个系统的并发度都由业务来确定,而不是靠这样的所谓的定律来支配着业务。
|
||||
|
||||
如果我们做了大量的样本数据分析,最后确实得出了28的比例,我觉得那也是可以的。但是如果什么数据都没有分析,直接使用28比例来做评估和计算,那就跟耍流氓没有区别。
|
||||
|
||||
业务模型应该如何得到呢?这里有两种方式是比较合理的:
|
||||
|
||||
1. 根据生产环境的统计信息做业务比例的统计,然后设定到压力工具中。有很多不能在线上直接做压力测试的系统,都通过这种方式获取业务模型。
|
||||
1. 直接在生产环境中做流量复制的方式或压力工具直接对生产环境发起压力的方式做压力测试。这种方式被很多人称为全链路压测。其实在生产中做压力测试的方式,最重要的工作不是技术,而是组织协调能力。相信参与过的人都能体会这句话的重量。
|
||||
|
||||
### 响应时间的258原则合理吗?
|
||||
|
||||
对于响应时间,有很多人还在说着258或2510响应时间是业内的通用标准。然后我问他们这个标准的出处在哪里?谁写的?背景是什么?几乎没有人知道。真是不能想像,一个谁都不知道出处的原则居然会有那么大的传播范围,就像谣言一样,出来之后,再也找不到源头。
|
||||
|
||||
其实这是在80年代的时候,英国一家IT媒体对音乐缓冲服务做的一次调查。在那个年代,得到的结果是,2秒客户满意度不错;5秒满意度就下降了,但还有利润;8秒时,就没有利润了。于是他们就把这个统计数据公布了出来,这样就出现了258 principle,翻译成中文之后,它就像一个万年不变的定理,深深影响着很多人。
|
||||
|
||||
距离这个统计结果的出现,已经过去快40年了,IT发展的都能上天了,这个时间现在已经完全不适用了。所以,以后出去别再提258/2510响应时间原则这样的话了,太不专业。
|
||||
|
||||
那么响应时间如何设计比较合理呢?这里有两种思路推荐给你。
|
||||
|
||||
1. 同行业的对比数据。
|
||||
1. 找到使用系统的样本用户(越多越好),对他们做统计,将结果拿出来,就是最有效的响应时间的制定标准。
|
||||
|
||||
### 性能指标的计算方式
|
||||
|
||||
我们在网上经常可以看到有人引用这几个公式。
|
||||
|
||||
公式(1):
|
||||
|
||||
并发用户数计算的通用公式:$C = \frac{nL}{T}$
|
||||
|
||||
其中C是平均的并发用户数;n是login session的数量;L是login session的平均长度;T指考察的时间段长度。
|
||||
|
||||
公式(2):
|
||||
|
||||
并发用户数峰值: $C’ ≈ C+3\times\sqrt{C}$
|
||||
|
||||
C’指并发用户数的峰值,C就是公式(1)中得到的平均的并发用户数。该公式是假设用户的login session产生符合泊松分布而估算得到的。
|
||||
|
||||
仔细搜索之后发现会发现这两个公式的出处是2004年一个叫Eric Man Wong的人写的一篇名叫《Method for Estimating the Number of Concurrent Users》的文章。中英文我都反复看到很多篇。同时也会网上看到有些文章中把这个文章描述成“业界公认”的计算方法。
|
||||
|
||||
在原文中,有几个地方的问题。
|
||||
|
||||
1. C并不是并发用户,而是在线用户。
|
||||
1. 这两个公式做了很多的假设条件,比如说符合泊松分布什么的。为什么说这个假设有问题?我们都知道泊松分布是一个钟型分布,它分析的是一个系统在全周期中的整体状态。
|
||||
1. 如果要让它在实际的项目中得到实用,还需要有大量的统计数据做样本,代入计算公式才能验证它的可信度。
|
||||
1. 峰值的计算,我就不说了,我觉得如果你是做性能的,应该一看就知道这个比例不符合大部分真实系统的逻辑。
|
||||
1. 有些人把这两个公式和Little定律做比较。我要说Little定律是最基础的排队论定律,并且这个定律只说明了:系统中物体的平均数量等于物体到达系统的平均速率和物体在系统中停留的平均时间的乘积。我觉得这句话,就跟秦腔中的”出门来只觉得脊背朝后“是一样一样的。
|
||||
|
||||
有人说应该如何来做系统容量的预估呢。我们现在很多系统的预估都是在一定的假设条件之下的,之所以是预估,说明系统还不在,或者还没达到那样的量。在这种情况下,我们可以根据现有的数据,做统计分析、做排队论模型,进而推导以后的系统容量。
|
||||
|
||||
但是我们所有做性能的人都应该知道,系统的容量是演进来的,而不是光凭预估就可以得出准确数值的。
|
||||
|
||||
## 总结
|
||||
|
||||
今天的这一篇和前两篇文章是一个体系,我利用这三篇文章对当前的性能测试市场上的一些关键概念进行一些拆解。性能测试策略、性能测试场景、性能测试指标,这些关键的概念在性能测试中深深地影响着很多人。我们简化它的逻辑,只需要记住几个关键字就可以,其他的都不必使用。
|
||||
|
||||
<li>
|
||||
性能测试概念中:性能指标、性能模型、性能场景、性能监控、性能实施、性能报告。
|
||||
</li>
|
||||
<li>
|
||||
性能场景中:基准场景、容量场景、稳定性场景、异常场景。
|
||||
</li>
|
||||
<li>
|
||||
性能指标中:TPS、RT。 (记住T的定义是根据不同的目标来的)
|
||||
</li>
|
||||
|
||||
有了这些之后,一个清晰的性能框架就已经出现了。
|
||||
|
||||
## 思考题
|
||||
|
||||
你能思考一下,为什么258响应时间不合理吗?像“业务模型用28原则”这些看似常识性的知识点,错在哪里呢?
|
||||
|
||||
欢迎你在评论区写下你的思考,我会和你一起交流,也欢迎把这篇文章分享给你的朋友或者同事,一起交流一下。
|
||||
@@ -0,0 +1,228 @@
|
||||
<audio id="audio" title="04丨JMeter和LoadRunner:要知道工具仅仅只是工具" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/ea/25/eab398acb991f52e7279396b254b0b25.mp3"></audio>
|
||||
|
||||
做性能测试工作的人总是离不了性能测试工具,但当我们刚开始接触这类工具或者压测平台的时候,总是难免处在一种顾此失彼,焦虑又没想法的状态。
|
||||
|
||||
## 性能工程师的三大学习阶段
|
||||
|
||||
在我看来,对性能测试工程师本身来,多半会处在以下三个大的阶段。
|
||||
|
||||
### 性能工具学习期
|
||||
|
||||
JMeter和LoadRunner是我们常用的两个性能测试工具。曾经有人问我,应该学JMeter还是LoadRunner呢?我反问的是,你学这样的工具需要多久呢?一般对方因为初学并不清楚要多久,然后我会告诉他,如果你是认真努力的,想要全职学习,那么我觉得一个工具,纯从功能的使用的角度来说,自学两个星期应该就差不多了。如果你是在工作中学习,那就更简单了,工作中需要什么就学习什么,不用纠结。
|
||||
|
||||
而应该纠结的是什么呢?当你把JMeter、LoadRunner的基本功能学会了,你会发现这些工具其实就做了两件事情,做脚本和发压力。
|
||||
|
||||
但问题在于,脚本的逻辑和压力场景的逻辑,和工具本身无关,和业务场景有关。这时你可能就会问,场景怎么配置呢?
|
||||
|
||||
这才进入到了另一个阶段。
|
||||
|
||||
通常在这个阶段的时候,你会觉得自己有非常明确的疑问,有经验的人可能一句话就可以指点你了,解决掉你的疑问,就是告诉你选择什么工具,如何来用。
|
||||
|
||||
### 性能场景学习期
|
||||
|
||||
第二个阶段就是性能场景学习期。我们平时在很多场合下所说的场景范围都有些狭隘,觉得场景就是业务比例,就是用多少数据。而实际做过多个性能项目之后,你就会发现,工具中的一个小小的配置,也会对结果产生巨大的影响。
|
||||
|
||||
比如说压力策略,应该用一秒 Ramp up 10个用户,还是20个用户,还是100个用户?这应该怎么判断呢?
|
||||
|
||||
比如说,参数化数据应该用100条,还是100万条?还是有确定的值呢?有人说根据场景配置,可是根据什么样的场景怎么配置才合理呢?
|
||||
|
||||
比如说,在执行场景时应该看哪些数据?压力工具中的TPS、响应时间这些常规数据都会去看,其他的还要看什么呢?这就涉及到了监控策略。
|
||||
|
||||
再比如说,业务应该用什么样的比例设置到压力工具中?有人说直接在线上做测试不是挺直接?但是你知道什么样的业务可以,什么样的业务不可以吗?如何控制线上的性能测试?
|
||||
|
||||
在性能场景学习期这个阶段,你关心的将不再是工具的使用操作,而是如何做一个合理的性能测试。你可以学会调整业务比例,并设计到压力工具中;你可以学会参数化数据的提取逻辑;你可以学会场景中要观察哪些数据。
|
||||
|
||||
按照这个思路,再做几个项目,你就会慢慢摸着一些门道。
|
||||
|
||||
### 性能分析学习期
|
||||
|
||||
学会使用工具了,也有了场景设计的经验,通过监控工具也拿到了一堆大大小小的数据。可是,数据也太多了,还在不断的变化。我又怎么判断性能瓶颈在哪里呢?
|
||||
|
||||
做性能的人都会有这样的一个茫然。当你把一个性能测试结果发给了别人,别人会顺理成章地去问你:“响应时间为什么这么长?有没有优化空间?”
|
||||
|
||||
听到这种问题,你有没有无助的感觉?心里台词是:“我怎么知道?”但是嘴上却不敢说出来,因为似乎这是我应该给出的答案?
|
||||
|
||||
但是当你尝试给出答案时,你就进入了一个大坑,对这个问题做出回答,近乎一个无底洞,需要太多的基础知识,需要很强的逻辑分析,需要清晰的判断思路。
|
||||
|
||||
如果你到了这个阶段,你可能会发现自己走得非常痛苦,好像自己也不知道自己会什么,不会什么。要说工具吧,也完全会用,场景吧,也会配置,但为什么就是不会分析结果,不会整理数据,不会下结论呢?
|
||||
|
||||
但实际上,我觉得你不要焦虑自己不会什么,而应该把目光聚焦到你要解决的问题上。问题的解决,靠的是思维逻辑,靠的是判断,而不是靠工具。
|
||||
|
||||
也就是说,这时面对问题,你应该说的是“我想要看什么数据”,而不是“把数据都给我看看”。
|
||||
|
||||
看到这里,希望你能清晰地理解这两者之间的区别。
|
||||
|
||||
## 公司性能团队成长阶段
|
||||
|
||||
我刚才分析了一下作为个人的性能工程师是如何一步步成长的,在实际工作中,我们更多的需要与团队合作,团队的成长与我们个人的成长息息相关。
|
||||
|
||||
对于一个公司的一个性能团队来说,大概会处在这些阶段。
|
||||
|
||||
### 性能团队初建
|
||||
|
||||
这时的团队,可以执行场景,可以拿出数据,但工作出的结果并不理想。团队整体的价值就体现在每天跟着版本跑来跑去,一轮轮地测试下去,一个版本短则一两个星期,长则一个月。没有时间去考虑测试结果对整个软件生命周期的价值,在各种琐碎的项目中疲于奔命。做脚本,拿出TPS和响应时间,做版本基线比对,出数据罗列式的性能测试报告。
|
||||
|
||||
唉,想想人生就这么过去了,真是心有不甘。这时有多少人希望能有一个性能测试平台来拯救团队啊。
|
||||
|
||||
### 性能团队初成熟
|
||||
|
||||
到了这个阶段,团队已经可以应付版本的更迭带来的性能工作压力,团队合作良好,稍有余力,开始考虑团队价值所在,在公司的组织结构中应该承担什么样的职责。在产品的流水线上终于可以占有一席之地了。这样很好,只是从实际的技术细节上来说,仍然没有摆脱第一阶段中琐碎的工作,没有把性能的价值体现出来,只是一个报告提供机器。
|
||||
|
||||
这时就需要考虑平台上是不是可以加个SLA来限制一下?在各个流程的关卡上,是不是可以做些性能标准?是不是该考虑下准入准出规则了?是的,这时一个团队开始慢慢走向成熟,站住脚之后要开始争取尊重了。
|
||||
|
||||
### 性能团队已成熟
|
||||
|
||||
有了标准、流程,团队的合作能力也成熟了之后,团队“是时候展示真正的实力了”。但问题来了,什么才是性能团队的真正实力呢?
|
||||
|
||||
直观上说,主要体现在一下几个方面。
|
||||
|
||||
**1. 通过你的测试和分析优化之后,性能提升了多少?**
|
||||
|
||||
这是一句非常简单直接的话。但是我相信有很多做性能测试工程师的人回答不出这样的问题。因为看着混乱的TPS曲线,自己都已经晕了,谁还知道性能提升了多少呢?
|
||||
|
||||
而一个成熟的团队应该回答的是:提升了10倍,我们调优了什么。这样的回答有理有据,底气十足。
|
||||
|
||||
**2. 通过你的测试和分析优化之后,节省了多少成本?**
|
||||
|
||||
这个问题就没有那么好回答了,因为你要知道整体的容量规划,线上的真实运营性能。如果之前的版本用了200台机器,而通过我们的测试分析优化之后,只用到了100台机器,那成本就很明显了。
|
||||
|
||||
但是,在我的职业生涯中,很少看到有人这样来体现性能存在的价值。有些场合是不需要这样体现,有些场合是不知道这样体现。
|
||||
|
||||
## 对个人以及团队来说,工具应该如何选择
|
||||
|
||||
理顺了性能测试工程师和性能团队的成长路径,下面我们来说说个人或者团队选择工具的时候,应该如何考量。
|
||||
|
||||
在我十几年工作的生涯中,可以说有很多性能工具都是知道的,但是要说起用得熟练的,也无非就是那几个市场占有率非常高的工具。
|
||||
|
||||
下面列一下市场上大大小小、老老少少、长长短短的性能测试工具,以备大家查阅。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/5b/a8/5bb101eb5aae149ae3488a920b4213a8.jpg" alt="">
|
||||
|
||||
市面上大大小小的性能测试工作一共有四十余种。这里面有收费的,也有免费的;有开源的,有闭源的;有新鲜的,有不新鲜的;有活跃的,有半死不活的;有可以监控系统资源的,有只能做压力发起的。
|
||||
|
||||
你是不是有一种生无可恋的感觉?一个性能测试而已,有必要搞出这么多工具吗?
|
||||
|
||||
然而,你要记住,这些都是压力发起工具。
|
||||
|
||||
下面我对一些比较常见的工具做下比对,这些工具主要包括Apache JMeter、HP LoadRunner、Silk Performer、Gatling、nGrinder、Locust和Tsung。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/92/8c/922eb45247344025f473d4649672a28c.jpg" alt="">
|
||||
|
||||
仅比对这几个工具吧,因为从市场上来说,这几个算是经常看到的工具,以后我们再加入其他的工具和其他的属性。我们现在只说性能工具,不说一些企业做的性能平台云服务,因为云服务都是对企业来说的,我们放到后面再讲。
|
||||
|
||||
你从网络上可以很容易地找到这几个工具的特点,这几个都支持分布式。从上面那张表格中,你可以很容易对比出来,知道自己应该学什么工具了。
|
||||
|
||||
Gatling有免费版和收费版,基于Scala语言,而Scala又是基于Java的,你看这复杂的关系就让人不想用,但是这个工具性能很高,虽说只支持HTTP,但是由于支持Akka Actors和Async IO,可以达到很高的性能。Actors简化并发编译的异步消息特性让Gatling性能很高。
|
||||
|
||||
Locust这个工具是基于Python的,中文名翻译过来就是蝗虫,这名字取得挺有意思。在一个压力场景下,对服务器来说确实就像一堆蝗虫来了。
|
||||
|
||||
对市场的占有率来说,JMeter和LoadRunner以绝对的优势占据前两名,同时JMeter又以绝对的优势占据第一名。
|
||||
|
||||
下面来看一下,这两个工具的热度趋势。
|
||||
|
||||
这是全球范围近5年JMeter和LoadRunner热度(红色线是LoadRunner,蓝色线是JMeter):
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/5d/82/5da3934e9b6956f0406af7596f35c582.png" alt="">
|
||||
|
||||
中国范围近5年JMeter和LoadRunner热度:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/01/96/0189855f2bb8c8539dac692214a80696.png" alt="">
|
||||
|
||||
从上面的比对来看,我们可以很容易发现,近五年来,LoadRunner就一直在走下坡路,而JMeter一直处在上升的趋势。
|
||||
|
||||
## JMeter和LoadRunner的历史兴衰
|
||||
|
||||
我下面只说一下JMeter和LoadRunner的历史,让你对性能工具的兴衰史有一定的了解。
|
||||
|
||||
先说说LoadRunner吧,应该说,LoadRunner的历史,就是一段悲惨的回忆。2006年11月份以前,在Mercury时代,LoadRunner由于市场策略和工具优势很快占了第一名,势头很猛。当时还有另一个同样功能的工具Silk Performer,被打压得几乎抬不起头来。06年以后,Mercury以45亿美元被HP收购,包括QC、QTP等工具。但从那之后,LoadRunner的体积就在飞速膨胀,8.1的LoadRunner只有600M左右(如果我没记错的话),经历了几个版本的迭代,LoadRunner成功膨胀到4个G,并在后面规划performance center,在各地做质量中心。HP这一步步走得理直气壮,把市场折腾没了。现在LoadRunner如果想装到一台压力机上,都是很吃力的事情。我要是用的话,宁愿在XP系统上安装8.1版本,速度飞快。2016年,HPE和MicroFocus合并,LoadRunner也成了MicroFous产品线的一部分,搞到现在,在中国的市场依然疲软。
|
||||
|
||||
而拥有同样竞品工具Silk Performer、Silk Test和Silk Test Manager的Segue公司,同年仅以1亿美元被另一个企业Borland收购。3年之后,Borland连同自己,以7500万美元卖给了MicroFocus。
|
||||
|
||||
至此,MicroFocus同时拥有了LoadRunner和Silk Performer。但可惜的是,这也照样干不过一个无心插柳柳成荫的开源工具JMeter。
|
||||
|
||||
JMeter的历史,可以说是屌丝逆袭的典型案例。1998年,Apache基金会的Stefano Mazzocchi是它最初的开发者,当时他只是为了测试Apache JServlet的性能(这个项目后来被Tomcat取代),后来JMeter被重构,又被用来测试Tomcat。其实一开始,JMeter的功能很简单。但是Apache Tomcat的势头实在是阻挡不住,再加上Java市场覆盖率实在是太高了,而JMeter做为一个开源免费的Java压力工具,有着众多的contributors,顶着Apache的大旗,想失败都难。就像ab工具是为了测试Apache HTTP server一样,JMeter应该说是和Apache Tomcat一起成长的。
|
||||
|
||||
与此同时,还有另一个Java开源工具The Grinder,这个工具的主要贡献者是Philip Aston、Calum Fitzgerald。
|
||||
|
||||
当时有一个开源测试平台叫NGrinder,是韩国公司NHN开源的。有很多所谓企业内部自研发的性能测试平台,就是从NGrinder借鉴来的,而NGrinder就是以The Grinder为基础开发的。可惜的是,The Grinder没有Apache这样的平台,作为一个很优秀的工具,它的维护更新还是不够快,不过NGrinder也给它带来了一定的荣耀。
|
||||
|
||||
到现在为止,JMeter还没有一个非常成熟的云测试平台支撑它,只有一些商业公司改动,加一些管理和项目属性,做为企业内部平台使用。还有一些企业把JMeter改造成商业产品,加上云基础架构的管理功能,就成了一套完整的商业平台,再加上炫丽的操作页面,棒棒的,有没有?
|
||||
|
||||
那么你有没有想过,为什么没有以JMeter为基础的开源云测试平台呢?难道JMeter的热爱者看不到云测试平台的价值吗?在我看来,做为性能测试工具,它实在是没有必要做成一个开源的测试平台,因为轮子就是轮子,要装成什么样的车就自己装吧。要是再换个角度来说,性能测试真的有必要用平台吗?
|
||||
|
||||
## 使用性能测试工具的误区在哪里
|
||||
|
||||
现在很多人都是看互联网大厂的技术栈,但是有没有想过自己企业需要的到底是什么样的产品?曾经有个测试工程师跟我说,他们公司为了解决性能问题,特意买了压测云服务,花了20万,结果问题还是没找出来。
|
||||
|
||||
所以工具应该如何用,完全取决于用的人,而不是工具本身。
|
||||
|
||||
压测工具也好,压测平台也好,都没有一个工具可以直接告诉你瓶颈在哪里,能告诉你的只是数据是什么。分析只有靠自己,在这个过程中,我们也会用到很多的分析剖析工具,用这些工具的人也都会知道,工具也只提供数据,不会告诉你瓶颈点在哪里。
|
||||
|
||||
那这个时候就有人提出疑问了:“有些工具不是说,上了这个工具之后,耗时一眼看透嘛?”是的呀,关键是你看过是什么耗时了吗?给你一个Java栈,那么长的栈,每个方法的消耗都给你,但是长的就肯定有问题吗?
|
||||
|
||||
关于剖析工具的,我们后面再写。本篇重点在压测工具上。
|
||||
|
||||
有人说JMeter BIO有问题,应该用AIO;有人说,压测工具没有后端系统性能监控数据,应该加一个监控插件。像JMeter中就有一个插件叫perfmon,把后端的系统资源拉到JMeter的界面中来看。在这一点上,LoadRunner老早就做过了,并且在之前的版本中还有个专门的组件叫tuning,目的就是把后端所有的系统、应用、数据库都配置到一个架构图中,压力一发起,就把有问题的组件标红。想法很好,可是这个功能为什么没有被广泛使用?当然,后面被HP收购后,这和HP的市场策略有关,但是在收购前的Mercury时代,该功能也没有被广泛使用。
|
||||
|
||||
我们从实际的生产场景来看,压测工具模拟的是真实用户,而监控在哪里,在运维后台里,数据的流向都不一样。如果你使用压测工具的同时,也把它做为收集性能监控数据的工具,本身流量就会冲突。
|
||||
|
||||
所以在压测工具中同时收集监控计数器,就是不符合真实场景的。
|
||||
|
||||
这样压测平台就有出现的必要了,我们可以看到出现了五花八门的压测平台,也会有后端监控数据的曲线,乍看起来,就两个字:全面!
|
||||
|
||||
可是,同样也没有告诉你瓶颈在哪里。
|
||||
|
||||
## 如果选择合适自己的工具?
|
||||
|
||||
所以我们用工具,一定要知道几点:
|
||||
|
||||
1. 工具能做什么?
|
||||
1. 工具不能做什么?
|
||||
1. 我们用工具的目标是什么?
|
||||
1. 当工具达不到目标时,我们怎么办?
|
||||
|
||||
把这几个问题在用工具之前就想清楚,才是个成熟的测试工程师,有这样的工程师的团队,才是成熟的性能测试团队(当然,成熟的测试团队还要有其他的技术)。
|
||||
|
||||
对企业,举例来说:
|
||||
|
||||
如果是一个需要支持万级、亿级TPS的电商网站,本身就是云基础架构,那么可能最简单的就是直接买这家的云压测工具就好了。
|
||||
|
||||
这样做的优点是不用再买机器做压力了。压力发起,主要就是靠压力机的量堆出来大并发。
|
||||
|
||||
但缺点也很明显,一是不能长期使用,长期用,费用就高了。二是数据也只能自己保存比对,如果测试和版本跨度大,还是要自己比对,无法自动比对。最后一个缺点就是 压力机不受控了。
|
||||
|
||||
所以如果有这样需求的企业,也基本上可以自己开发一套云压测工具了,从使用周期和长远的成本上来看,自已开发,都是最划算的。
|
||||
|
||||
如果是一个需要支持每秒100TPS的企业内部业务系统,就完全没必要买什么云服务了,自己找一台4C8G的机器,可能就压得够了。
|
||||
|
||||
这样的话完全可控,压测结果数据也都可以随时查看,可以留存。
|
||||
|
||||
如果是一个需要支持万级TPS,但又不能用云服务的事业单位或政企,比如,军工业,那只能自己搭建一套测试环境了。这样做的优点是完全内部可控,数据非常安全,但缺点就是投入成本高。
|
||||
|
||||
对私企来说,开源永远是最好的选择,成本低,但是需要相关人员能力稍强一些,因为没有技术支持。
|
||||
|
||||
对政企和事业单位来说,收费是一个好的选择,因为有第三方服务可以叫过来随时支持。
|
||||
|
||||
对一个做短平快项目的企业来说,云服务会是一个好选择,成本低,不用长期维护数据。
|
||||
|
||||
对想做百年老店的企业来说,肯定是自己开发平台,尽量不选择云服务,因为技术是需要积累的。
|
||||
|
||||
对个人来说呢,不用举例,压测工具市场,现在肯定是首选学习JMeter,其次是LoadRunner。
|
||||
|
||||
JMeter的势头已经很明显了,并且功能在慢慢扩展。开源免费是巨大的优势。
|
||||
|
||||
而LoadRunner,不管它的市场现在有多凋零,它仍然是性能测试市场上,功能最为齐全的工具,没有之一。
|
||||
|
||||
## 总结
|
||||
|
||||
总体来说,性能测试工具的市场中,可以说现在的工具已经种类繁多了,并且各有优点。在项目中,根据具体的实施成本及企业中的规划,选择一个最适合的就可以了。也可以用它们来组建自己的平台。但是请注意, 不要觉得做平台可以解决性能测试的问题,其实平台只是解决了人工的成本。
|
||||
|
||||
如果单纯为了追潮流而把性能测试工具的使用成本升得特别高,那就不划算了。
|
||||
|
||||
## 思考题
|
||||
|
||||
今天的内容有点多,我提几个思考题,你就当是对文章的回顾吧。
|
||||
|
||||
你觉得企业选择性能工具应该考虑哪些方面呢?以及性能测试工具中是否必须做监控呢?
|
||||
|
||||
欢迎你在评论区写下你的思考,也欢迎把这篇文章分享给你的朋友或者同事,一起交流一下。
|
||||
197
极客时间专栏/性能测试实战30讲/第一模块:性能测试基础篇/05丨指标关系:你知道并发用户数应该怎么算吗?.md
Normal file
197
极客时间专栏/性能测试实战30讲/第一模块:性能测试基础篇/05丨指标关系:你知道并发用户数应该怎么算吗?.md
Normal file
@@ -0,0 +1,197 @@
|
||||
<audio id="audio" title="05丨指标关系:你知道并发用户数应该怎么算吗?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/28/05/28544be7a627d2f053929deeafb01305.mp3"></audio>
|
||||
|
||||
我在性能综述的那三篇文章中,描述了各种指标,比如TPS、RPS、QPS、HPS、CPM等。我也强调了,我们在实际工作的时候,应该对这些概念有统一的认识。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/d4/5d/d46c772ccce3e8270e5f7be7e915755d.jpg" alt="">
|
||||
|
||||
这样的话,在使用过程中,一个团队或企业从上到下都具有同样的概念意识,就可以避免出现沟通上的偏差。
|
||||
|
||||
我说一个故事。
|
||||
|
||||
我以前接触过一个咨询项目。在我接触之前,性能测试团队一直给老板汇报着一个数据,那就是10000TPS。并且在每个版本之后,都会出一个性能测试报告,老板一看,这个数据并没有少于10000TPS,很好。 后来,我进去一看,他们一直提的这个10000TPS指的是单业务的订单,并且是最基础的订单逻辑。那么问题来了,如果混合起来会怎么样呢?于是我就让他们做个混合容量场景,显然,提容量不提混合,只说单接口的容量是不能满足生产环境要求的。
|
||||
|
||||
结果怎么样呢?只能测试到6000TPS。于是我就要去跟老板解释说系统达到的指标是6000TPS。老板就恼火了呀,同样的系统,以前报的一直是10000TPS,现在怎么只有6000TPS了?不行,你们开发的这个版本肯定是有问题的。于是老板找到了研发VP,研发VP找到了研发经理,研发经理找了研发组长,研发组长又找到了开发工程师,开发工程师找到了我。我说之前不是混合场景的结果,现在混合容量场景最多达到6000TPS,你们可以自己来测。
|
||||
|
||||
然后证明,TPS确实只能达到6000。然后就是一轮又一轮的向上解释。
|
||||
|
||||
说这个故事是为了告诉你,你用TPS也好,RPS也好,QPS也好,甚至用西夏文来定义也不是不可以,只要在一个团队中,大家都懂就可以了。
|
||||
|
||||
但是,在性能市场上,我们总要用具有普适性的指标说明,而不是用混乱的体系。
|
||||
|
||||
在这里,我建议用TPS做为关键的性能指标。那么在今天的内容里,我们就要说明白TPS到底是什么。在第3篇文章中,我提到过在不同的测试目标中设置不同的事务,也就是TPS中的T要根据实际的业务产生变化。
|
||||
|
||||
那么问题又来了,TPS和并发数是什么关系呢? 在并发中谁来承载”并发“这个概念呢?
|
||||
|
||||
说到这个,我们先说一下所谓的“绝对并发”和“相对并发”这两个概念。绝对并发指的是同一时刻的并发数;相对并发指的是一个时间段内发生的事情。
|
||||
|
||||
你能详细说一下这两个概念之间的区别吗?如果说不出来那简直太正常了,因为这两个概念把事情说得更复杂了。
|
||||
|
||||
## 什么是并发
|
||||
|
||||
下面我们就来说一下“并发”这个概念。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/0e/96/0ef2fca88f59342a64084e147b33af96.jpg" alt="">
|
||||
|
||||
我们假设上图中的这些小人是严格按照这个逻辑到达系统的,那显然,系统的绝对并发用户数是4。如果描述1秒内的并发用户数,那就是16。是不是显而易见?
|
||||
|
||||
但是,在实际的系统中,用户通常是这样分配的:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/1e/23/1e42cc116598acb7c703eec95a7c6723.png" alt="">
|
||||
|
||||
也就是说,这些用户会分布在系统中不同的服务、网络等对象中。这时候”绝对并发“这个概念就难描述了,你说的是哪部分的绝对并发呢?
|
||||
|
||||
要说积分服务,那是2;要说库存服务,那是5;要说订单服务,它自己是5个请求正在处理,但同时它又hold住了5个到库存服务的链接,因为要等着它返回之后,再返回给前端。所以将绝对并发细分下去之后,你会发现头都大了,不知道要描述什么了。
|
||||
|
||||
有人说,我们可以通过CPU啊,I/O啊,或者内存来描述绝对并发,来看CPU在同一时刻处理的任务数。如果是这样的话,绝对并发还用算吗?那肯定是CPU的个数呀。有人说CPU 1ns就可以处理好多个任务了,这里的1ns也是时间段呀。要说绝对的某个时刻,任务数肯定不会大于CPU物理个数。
|
||||
|
||||
所以“绝对并发”这个概念,不管是用来描述硬件细化的层面,还是用来描述业务逻辑的层面,都是没什么意义的。
|
||||
|
||||
我们只要描述并发就好了,不用有“相对”和“绝对”的概念,这样可以简化沟通,也不会出错。
|
||||
|
||||
那么如何来描述上面的并发用户数呢?在这里我建议用TPS来承载“并发”这个概念。
|
||||
|
||||
并发数是16TPS,就是1秒内整个系统处理了16个事务。
|
||||
|
||||
这样描述就够了,别纠结。
|
||||
|
||||
## 在线用户数、并发用户数怎么计算
|
||||
|
||||
那么新问题又来了,在线用户数和并发用户数应该如何算呢?下面我们接着来看示意图:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/1b/99/1beff8afb0116c72dd428eba9d329299.jpg" alt="">
|
||||
|
||||
如上图所示,总共有32个用户进入了系统,但是绿色的用户并没有任何动作,那么显然,在线用户数是32个,并发用户数是16个,这时的并发度就是50%。
|
||||
|
||||
但在一个系统中,通常都是下面这个样子的。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/59/1c/59fd25efa2fdd259b4fc0b6b462a031c.jpg" alt="">
|
||||
|
||||
为了能hold住更多的用户,我们通常都会把一些数据放到Redis这样的缓存服务器中。所以在线用户数怎么算呢,如果仅从上面这种简单的图来看的话,其实就是缓存服务器能有多大,能hold住多少用户需要的数据。
|
||||
|
||||
最多再加上在超时路上的用户数。如下所示:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/4b/10/4bbf31a73fd4ccf6245634b8c7eb2910.jpg" alt="">
|
||||
|
||||
所以我们要是想知道在线的最大的用户数是多少,对于一个设计逻辑清晰的系统来说,不用测试就可以知道,直接拿缓存的内存来算就可以了。
|
||||
|
||||
假设一个用户进入系统之后,需要用10k内存来维护一个用户的信息,那么10G的内存就能hold住1,048,576个用户的数据,这就是最大在线用户数了。在实际的项目中,我们还会将超时放在一起来考虑。
|
||||
|
||||
但并发用户数不同,他们需要在系统中执行某个动作。我们要测试的重中之重,就是统计这些正在执行动作的并发用户数。
|
||||
|
||||
当我们统计生产环境中的在线用户数时,并发用户数也是要同时统计的。这里会涉及到一个概念:**并发度**。
|
||||
|
||||
要想计算并发用户和在线用户数之间的关系,都需要有并发度。
|
||||
|
||||
做性能的人都知道,我们有时会接到一个需求,那就是一定要测试出来**系统最大在线用户数是多少**。这个需求怎么做呢?
|
||||
|
||||
很多人都是通过加思考时间(有的压力工具中叫等待时间,Sleep时间)来保持用户与系统之间的session不断,但实际上的并发度非常非常低。
|
||||
|
||||
我曾经看到一个小伙,在一台4C8G的笔记本上用LoadRunner跑了1万个用户,里面的error疯狂上涨,当然正常的事务也有。我问他,你这个场景有什么意义,这么多错?他说,老板要一个最大在线用户数。我说你这些都错了呀。他说,没事,我要的是Running User能达到最大就行,给老板交差。我只能默默地离开了。
|
||||
|
||||
这里有一个比较严重的理解误区,那就是压力工具中的线程或用户数到底是不是用来描述性能表现的?我们通过一个示意图来说明:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/08/3c/0814da6123f7a7fefedc3a24f364ac3c.jpg" alt="">
|
||||
|
||||
通过这个图,我们可以看到一个简单的计算逻辑:
|
||||
|
||||
1. 如果有10000个在线用户数,同时并发度是1%,那显然并发用户数就是100。
|
||||
1. 如果每个线程的20TPS,显然只需要5个线程就够了(请注意,这里说的线程指的是压力机的线程数)。
|
||||
1. 这时对Server来说,它处理的就是100TPS,平均响应时间是50ms。50ms就是根据1000ms/20TPS得来的(请注意,这里说的平均响应时间会在一个区间内浮动,但只要TPS不变,这个平均响应时间就不会变)。
|
||||
1. 如果我们有两个Server线程来处理,那么一个线程就是50TPS,这个很直接吧。
|
||||
1. 请大家注意,这里我有一个转换的细节,那就是**并发用户数到压力机的并发线程数**。这一步,我们通常怎么做呢?就是基准测试的第一步。关于这一点,我们在后续的场景中交待。
|
||||
|
||||
而我们通常说的“并发”这个词,依赖TPS来承载的时候,指的都是Server端的处理能力,并不是压力工具上的并发线程数。在上面的例子中,我们说的并发就是指服务器上100TPS的处理能力,而不是指5个压力机的并发线程数。**请你切记这一点,以免沟通障碍**。
|
||||
|
||||
在我带过的所有项目中,这都是一个沟通的前提。
|
||||
|
||||
所以,我一直在强调一点,这是一个基础的知识:**不要在意你用的是什么压力工具,只要在意你服务端的处理能力就可以了**。
|
||||
|
||||
## 示例
|
||||
|
||||
上面说了这么多,我们现在来看一个实例。这个例子很简单,就是:
|
||||
|
||||
JMeter(1个线程) - Nginx - Tomcat - MySQL
|
||||
|
||||
通过上面的逻辑,我们先来看看JMeter的处理情况:
|
||||
|
||||
```
|
||||
summary + 5922 in 00:00:30 = 197.4/s Avg: 4 Min: 0 Max: 26 Err: 0 (0.00%) Active: 1 Started: 1 Finished: 0
|
||||
summary = 35463 in 00:03:05 = 192.0/s Avg: 5 Min: 0 Max: 147 Err: 0 (0.00%)
|
||||
summary + 5922 in 00:00:30 = 197.5/s Avg: 4 Min: 0 Max: 24 Err: 0 (0.00%) Active: 1 Started: 1 Finished: 0
|
||||
summary = 41385 in 00:03:35 = 192.8/s Avg: 5 Min: 0 Max: 147 Err: 0 (0.00%)
|
||||
summary + 5808 in 00:00:30 = 193.6/s Avg: 5 Min: 0 Max: 25 Err: 0 (0.00%) Active: 1 Started: 1 Finished: 0
|
||||
summary = 47193 in 00:04:05 = 192.9/s Avg: 5 Min: 0 Max: 147 Err: 0 (0.00%)
|
||||
|
||||
```
|
||||
|
||||
我们可以看到,JMeter的平均响应时间基本都在5ms,因为只有一个压力机线程,所以它的TPS应该接近1000ms/5ms=200TPS。从测试结果上来看,也确实是接近的。有人说为什么会少一点?因为这里算的是平均数,并且这个数据是30s刷新一次,用30秒的时间内完成的事务数除以30s得到的,但是如果事务还没有完成,就不会计算在内了;同时,如果在这段时间内有一两个时间长的事务,也会拉低TPS。
|
||||
|
||||
那么对于服务端呢,我们来看看服务端线程的工作情况。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/bd/55/bdce20f34b2e0689c21977859f54e155.png" alt="">
|
||||
|
||||
可以看到在服务端,我开了5个线程,但是服务端并没有一直干活,只有一个在干活的,其他的都处于空闲状态。
|
||||
|
||||
这是一种很合理的状态。但是你需要注意的是,这种合理的状态并不一定是对的性能状态。
|
||||
|
||||
1. 并发用户数(TPS)是193.6TPS。如果并发度为5%,在线用户数就是193.6/5%=3872。
|
||||
1. 响应时间是5ms。
|
||||
1. 压力机并发线程数是1。这一条,我们通常也不对非专业人士描述,只要性能测试工程师自己知道就可以了。
|
||||
|
||||
下面我们换一下场景,在压力机上启动10个线程。结果如下:
|
||||
|
||||
```
|
||||
summary + 11742 in 00:00:30 = 391.3/s Avg: 25 Min: 0 Max: 335 Err: 0 (0.00%) Active: 10 Started: 10 Finished: 0
|
||||
summary = 55761 in 00:02:24 = 386.6/s Avg: 25 Min: 0 Max: 346 Err: 0 (0.00%)
|
||||
summary + 11924 in 00:00:30 = 397.5/s Avg: 25 Min: 0 Max: 80 Err: 0 (0.00%) Active: 10 Started: 10 Finished: 0
|
||||
summary = 67685 in 00:02:54 = 388.5/s Avg: 25 Min: 0 Max: 346 Err: 0 (0.00%)
|
||||
summary + 11884 in 00:00:30 = 396.2/s Avg: 25 Min: 0 Max: 240 Err: 0 (0.00%) Active: 10 Started: 10 Finished: 0
|
||||
summary = 79569 in 00:03:24 = 389.6/s Avg: 25 Min: 0 Max: 346 Err: 0 (0.00%)
|
||||
|
||||
```
|
||||
|
||||
平均响应时间在25ms,我们来计算一处,(1000ms/25ms)*10=400TPS,而最新刷出来的一条是396.2,是不是非常合理?
|
||||
|
||||
再回来看看服务端的线程:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/59/90/596564dd3186769bdf546bfdc5bdae90.png" alt="">
|
||||
|
||||
同样是5个线程,现在就忙了很多。
|
||||
|
||||
1. 并发用户数(TPS)是396.2TPS。如果并发度为5%,在线用户数就是396.2/5%=7924。
|
||||
1. 响应时间是25ms。
|
||||
1. 压力机并发线程数是10。这一条,我们通常也不对非专业人士描述,只要性能测试工程师自己知道就可以了。
|
||||
|
||||
如果要有公式的话,这个计算公式将非常简单:
|
||||
|
||||
$TPS = \frac{1000ms}{响应时间(单位ms)}*压力机线程数$
|
||||
|
||||
我不打算再将此公式复杂化,所以就不再用字母替代了。
|
||||
|
||||
这就是我经常提到的,**对于压力工具来说,只要不报错,我们就关心TPS和响应时间就可以了,因为TPS反应出来的是和服务器对应的处理能力,至少压力线程数是多少,并不关键**。我想这时会有人能想起来JMeter的BIO和AIO之争吧。
|
||||
|
||||
你也许会说,这个我理解了,服务端有多少个线程,就可以支持多少个压力机上的并发线程。但是这取决于TPS有多少,如果服务端处理的快,那压力机的并发线程就可以更多一些。
|
||||
|
||||
这个逻辑看似很合理,但是通常服务端都是有业务逻辑的,既然有业务逻辑,显然不会比压力机快。
|
||||
|
||||
应该说,服务端需要更多的线程来处理压力机线程发过来的请求。所以我们用几台压力机就可以压几十台服务端的性能了。
|
||||
|
||||
如果在一个微服务的系统中,因为每个服务都只做一件事情,拆分得很细,我们要注意整个系统的容量水位,而不是看某一个服务的能力,这就是拉平整个系统的容量。
|
||||
|
||||
我曾经看一个人做压力的时候,压力工具中要使用4000个线程,结果给服务端的Tomcat上也配置了4000个线程,结果Tomcat一启动,稍微有点访问,CS就特别高,结果导致请求没处理多少,自己倒浪费了不少CPU。
|
||||
|
||||
## 总结
|
||||
|
||||
通过示意图和示例,我描述了在线用户数、并发用户数、TPS(这里我们假设了一个用户只对应一个事务)、响应时间之间的关系。有几点需要强调:
|
||||
|
||||
1. 通常所说的并发都是指服务端的并发,而不是指压力机上的并发线程数,因为服务端的并发才是服务器的处理能力。
|
||||
1. 性能中常说的并发,是用TPS这样的概念来承载具体数值的。
|
||||
1. 压力工具中的线程数、响应时间和TPS之间是有对应关系的。
|
||||
|
||||
这里既没有复杂的逻辑,也没有复杂的公式。希望你在性能项目中,能简化概念,注重实用性。
|
||||
|
||||
## 思考题
|
||||
|
||||
如果你吸收了今天的内容,不妨思考一下这几个问题:
|
||||
|
||||
如何理解“服务端的并发能力”这一描述?我为什么不提倡使用“绝对并发”和“相对并发”的概念呢?以及,我们为什么不推荐用CPU来计算并发数?
|
||||
436
极客时间专栏/性能测试实战30讲/第一模块:性能测试基础篇/06丨倾囊相授:我毕生所学的性能分析思路都在这里了.md
Normal file
436
极客时间专栏/性能测试实战30讲/第一模块:性能测试基础篇/06丨倾囊相授:我毕生所学的性能分析思路都在这里了.md
Normal file
@@ -0,0 +1,436 @@
|
||||
<audio id="audio" title="06丨倾囊相授:我毕生所学的性能分析思路都在这里了" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/7b/d6/7be1cd5c82c60c1592a307d136d190d6.mp3"></audio>
|
||||
|
||||
我还年轻的时候,经常听一些大会或者演讲。有些人说,思路逻辑非常重要。我那时就想,你肯定是瞎忽悠的,因为我怎么就没听懂你说的思路呢?
|
||||
|
||||
而现在轮到自己来写或者讲一些东西的时候,才发现他们说得很对,而我之所以不理解,也是有原因的。
|
||||
|
||||
性能分析思路和具体的实现之间,有一道鸿沟,那就是操作的能力。之前我为什么听不懂那些人的思路,其实是因为我没有操作的功底。
|
||||
|
||||
而有了操作的功底之后,还有一个大的鸿沟要越过去,那就是从操作到对监控计数器的理解。这一步可以说让很多性能测试人员都望而却步了。
|
||||
|
||||
但是这还不算完,这一步迈过去之后,还有一个跳跃,就是相关性分析和证据链分析的过程。
|
||||
|
||||
如此一来,就会得到一张**性能测试分析的能力阶梯视图**,如下:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/1d/f8/1dbe8969f74d0d314675cb8bc24965f8.jpg" alt="">
|
||||
|
||||
1. 工具操作:包括压力工具、监控工具、剖析工具、调试工具。
|
||||
1. 数值理解:包括上面工具中所有输出的数据。
|
||||
1. **趋势分析、相关性分析、证据链分析**:就是理解了工具产生的数值之后,还要把它们的逻辑关系想明白。这才是性能测试分析中最重要的一环。
|
||||
1. 最后才是调优:有了第3步之后,调优的方案策略就有很多种了,具体选择取决于调优成本和产生的效果。
|
||||
|
||||
那么怎么把这些内容都融会贯通呢?下面我们就来说说性能测试分析的几个重要环节。
|
||||
|
||||
应该说,从我十几年的性能工作中,上面讲的这些内容是我觉得最有价值的内容了。在今天的文章中,我们将对它做一次系统的说明。我先把**性能分析思路**大纲列在这里:
|
||||
|
||||
1. 瓶颈的精准判断;
|
||||
1. 线程递增的策略;
|
||||
1. 性能衰减的过程;
|
||||
1. 响应时间的拆分;
|
||||
1. 构建分析决策树;
|
||||
1. 场景的比对。
|
||||
|
||||
## 瓶颈的精准判断
|
||||
|
||||
### TPS曲线
|
||||
|
||||
对性能瓶颈做出判断是性能分析的第一步,有了问题才能分析调优。
|
||||
|
||||
之前有很多人在描述性能测试的过程中,说要找到性能测试中曲线上的“拐点”。我也有明确说过,大部分系统其实是没有明确的拐点的。
|
||||
|
||||
举例来说,TPS的视图如下:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/67/4e/67613a7c330a115064167cac05d82d4e.png" alt="" title="TPS图1">
|
||||
|
||||
显然,这是一个阶梯式增加的场景,非常好。但是拐点在哪呢?有人说,显然在1200TPS左右的时候。也有人说了,显然是到1500TPS才是拐点呀。但是也有人说,这都已经能到2000TPS了,显然2000TPS是拐点。
|
||||
|
||||
我们再来看一下这张图对应的响应时间视图:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/67/51/67b8573993a39a68e923e78e19442151.png" alt="" title="响应时间图1">
|
||||
|
||||
是不是有人要说响应时间为4.5ms时是拐点了?
|
||||
|
||||
其实这些对拐点的判断,都是不合理的。如果我们对TPS的增加控制得更为精准的话,那么这个TPS的增加是有一个有清晰的弧度,而不是有一个非常清晰的拐点。
|
||||
|
||||
但是至少我们可以有一个非常明确的判断,那就是瓶颈在第二个压力阶梯上已经出现了。因为响应时间增加了,TPS增加得却没有那么多,到第三个阶梯时,显然增加的TPS更少了,响应时间也在不断地增加,所以,性能瓶颈在加剧,越往后就越明显。
|
||||
|
||||
那么我们的判断就是:
|
||||
|
||||
1. 有瓶颈!
|
||||
1. 瓶颈和压力有关。
|
||||
1. 压力呈阶梯,并且增长幅度在衰减。
|
||||
|
||||
如果你觉得上面的瓶颈还算清晰的话,那么我们再来看一张图:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/16/58/16e821606d14d3a0061244c1740a3b58.png" alt="" title="TPS图2">
|
||||
|
||||
在这个TPS的曲线中,你还能判断出拐点在哪吗?
|
||||
|
||||
显然是判断不出来拐点的,但是我们根据图得出以下几个结论:
|
||||
|
||||
1. 有瓶颈!
|
||||
1. 瓶颈和压力有关。
|
||||
1. 压力也是阶梯的,但是并没有明确的拐点。
|
||||
|
||||
我们再来看一个TPS图:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/3c/fb/3cc3ee474966a49f845fcfc52cb337fb.png" alt="" title="TPS图3">
|
||||
|
||||
看到这张图,是不是明显感觉系统有瓶颈呢?那么瓶颈是不是和压力大小有关呢?
|
||||
|
||||
这种比较有规律的问题,显然不是压力大小的原因。为什么呢?因为TPS周期性地出现降低,并且最大的TPS也都恢复到了差不多的水位上。所以,即使是压力降低,也最多降低最大的TPS水位,会让问题出现得更晚一点,但是不会不出现。
|
||||
|
||||
综合以上,如果画一个示意图的话,TPS的衰减过程大概会如下所示:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/a8/b4/a8ea90b0516f081058bf78bc24ed94b4.png" alt="">
|
||||
|
||||
1. 随着用户数的增加,响应时间也在缓慢增加。
|
||||
1. TPS前期一直都有增加,但是增加的幅度在变缓,直到变平。
|
||||
|
||||
在这样的趋势图中,我们是看不到明确的拐点的。但是我们能做的清晰的判断就是:有瓶颈!
|
||||
|
||||
所以对TPS曲线来说,它可以明确告诉我们的就是:
|
||||
|
||||
1. 有没有瓶颈:其实准确说所有的系统都有性能瓶颈,只看我们在哪个量级在做性能测试了。
|
||||
1. 瓶颈和压力有没有关系:TPS随着压力的变化而变化,那就是有关系。不管压力增不增加,TPS都会出现曲线趋势问题,那就是无关。
|
||||
|
||||
这时你可能会问,为什么不看响应时间就武断地下此结论呢?其实响应时间是用来判断业务有多快的,而TPS才是用来判断容量有多大的。
|
||||
|
||||
### 响应时间的曲线
|
||||
|
||||
我们还是来看看响应时间,下面看一张响应时间图:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/06/a7/061e77ee8dc20c9c1cd1ae1f6a27d7a7.png" alt="">
|
||||
|
||||
它对应的线程图是:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/32/8d/32ab933156f0ba11a1f08489bf62398d.png" alt="">
|
||||
|
||||
多明显的问题,随着线程的增多,响应时间也在增加,是吧。再来看它们对应的TPS图:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/c9/48/c9f48c144a3663b3779832f62e25e148.png" alt="">
|
||||
|
||||
到第40个线程时,TPS基本上达到上限,为2500左右。响应时间随着线程数的增加而增加了,系统的瓶颈显而易见地出现了。
|
||||
|
||||
但是,如果只让你看TPS曲线,你是不是也会有同样的判断?那就是:有瓶颈!并且和压力有关?所以说,其实TPS就可以告诉我们系统有没有瓶颈了,而响应时间是用来判断业务有多快的。
|
||||
|
||||
后面我们还会提到响应时间会是性能分析调优的重要分析对象。
|
||||
|
||||
## 线程递增的策略
|
||||
|
||||
讲完响应时间之后,我们再来看下线程递增。
|
||||
|
||||
在见识了很多性能测试人员做的场景之后,必须得承认,有些场景的问题太多了。
|
||||
|
||||
首先,我们来看两个场景的执行对比。
|
||||
|
||||
场景1的线程图:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/68/d7/68b4c0811e61657432a8b4ceb1c7dbd7.png" alt="">
|
||||
|
||||
场景1的TPS图:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/ac/b5/aca9cb229a4503b0ebba911c38cf0bb5.png" alt="">
|
||||
|
||||
场景1的响应时间图:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/bd/af/bda2ca6d65527aa6f3a435573eaefeaf.png" alt="">
|
||||
|
||||
场景2的线程图:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/b1/7a/b105147c5cfbdc66fa708daae0a1977a.png" alt="">
|
||||
|
||||
场景2的TPS图:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/8a/2a/8a849b11b9be9beffebf0c4579c4a12a.png" alt="">
|
||||
|
||||
场景2的响应时间图:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/a9/e4/a9e3d6318a1ef1d7fc28e9b45c4733e4.png" alt="">
|
||||
|
||||
这两个场景的比对如下:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/87/e6/87a445e7c292ca19f8f71b7dface94e6.png" alt="">
|
||||
|
||||
有了这些对比数据之后,你是不是觉得哪里似乎是有问题的?
|
||||
|
||||
对的!
|
||||
|
||||
TPS都是达到400,但两个场景中线程递增的策略不同,产生的响应时间完全不同。虽然都没有报错,但是第一种场景是完全不符合真实的业务场景的。这是为什么呢?
|
||||
|
||||
在场景的执行过程中,首先,响应时间应该是从低到高的,而在场景1中不是这样。其次,线程应该是递增的,而场景1并没有这样做(这里或许有人会想到秒杀的场景,认为场景1符合秒杀的业务设定,这个问题我们稍后提及)。最后,在两个场景中,TPS的上限都达到了400TPS。但是你可以看到,在场景2中,只要40个线程即可达到,但场景1中居然用到了500线程,显然压力过大,所以响应时间才那么长。
|
||||
|
||||
其实在生产环境中,像场景1这样的情形是不会出现的。如果它出现了,那就是你作为性能测试的责任,因为你没有给出生产环境中应该如何控制流量的参数配置说明。
|
||||
|
||||
同时,我们从上面的场景对比可以看到,**对一个系统来说,如果仅在改变压力策略(其他的条件比如环境、数据、软硬件配置等都不变)的情况下,系统的最大TPS上限是固定的**。
|
||||
|
||||
场景2使用了递增的策略,在每个阶梯递增的过程中,出现了抖动,这就明显是系统设置的不合理导致的。设置不合理,有两种可能性:1. 资源的动态分配不合理,像后端线程池、内存、缓存等等;2. 数据没有预热。
|
||||
|
||||
我们再回到之前说的秒杀场景。
|
||||
|
||||
说到秒杀场景,有人觉得用大线程并发是合理的,其实这属于认识上的错误。因为即使线程数增加得再多,对已经达到TPS上限的系统来说,除了会增加响应时间之外,并无其他作用。所以我们描述系统的容量是用系统当前能处理的业务量(你用TPS也好,RPS也好,HPS也好,它们都是用来描述服务端的处理能力的),而不是压力工具中的线程数。这一点,我在第5篇文章中已经做了详细的解析,你可以回去再看看。
|
||||
|
||||
那么,对于场景中线程(有些工具中叫虚拟用户)递增的策略,我们要做到以下几点:
|
||||
|
||||
1. 场景中的线程递增一定是连续的,并且在递增的过程中也是有梯度的。
|
||||
1. 场景中的线程递增一定要和TPS的递增有比例关系,而不是突然达到最上限。后面在场景的篇幅中我们会再说它们之间的比例关系。
|
||||
1. 上面两点针对的是常规的性能场景。对于秒杀类的场景,我们前期一定是做好了系统预热的工作的,在预热之后,线程突增产生的压力,也是在可处理范围的。这时,我们可以设计线程突增的场景来看系统瞬间的处理能力。如果不能模拟出秒杀的陡增,就是不合理的场景。
|
||||
|
||||
这里给出我做性能场景递增的经验值:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/33/9c/3341781894e1bbf771e8a35781e7df9c.png" alt="">
|
||||
|
||||
当然这里也不会是放在哪个系统中都适合的递增幅度,你还是要根据实际的测试过程来做相应的判断。
|
||||
|
||||
有了这些判断之后,相信大家都能做出合理的场景来了。
|
||||
|
||||
## 性能衰减的过程
|
||||
|
||||
有了瓶颈的判断能力,也有了线程递增的意识,那么下面在场景执行中,我们就要有判断性能衰减的能力了吧。
|
||||
|
||||
来,我们先看一个压力过程中产生的结果图。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/eb/ce/eb938af9e8bd5c4fcb170855102e23ce.png" alt="">
|
||||
|
||||
在递增的压力过程中,随着用户数的增加。我们可以做几次计算。
|
||||
|
||||
第一次计算,在线程达到24时,TPS为1810.6,也就是每线程每秒发出75.44个请求。
|
||||
|
||||
第二次计算,在线程达到72时,TPS为4375.1,也就是每线程每秒发出60.77个请求。
|
||||
|
||||
第三次计算,在线程达到137时,TPS为5034,也就是每线程每秒发出36.74个请求。
|
||||
|
||||
通过这三次计算,我们是不是可以看到,每线程每秒发出的请求数在变少,但是整体TPS是在增加的。
|
||||
|
||||
我们有很多做性能测试的人,基本上,只看TPS和响应时间的时候,在上面这个示例中,肯定会一直往上加用户。虽然响应时间在增加,但是增加得也不多嘛。
|
||||
|
||||
但实际上,通过我们的计算可以知道,性能是在不断地衰减的。我们来看一张统计图:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/88/17/88f8facef19db7d6828fa64349483b17.png" alt="">
|
||||
|
||||
通过红线的大致比对可以知道,当每线程每秒的请求数降到55左右的时候,TPS就达到上限了,大概在5000左右,再接着往上增加线程已经没有用了,响应时间开始往上增加了。
|
||||
|
||||
这就是性能衰减的过程(题外话,在上图中,其实还有一个问题,就是在红线前面,性能在上升的过程中有几次抖动,这个抖动到后面变大了,也变频繁了,如果这是必然出现的抖动,那也是配置问题,希望你注意到这一点)。
|
||||
|
||||
为什么要这么细致地描述性能衰减的过程呢?
|
||||
|
||||
其实我就是想告诉你,**只要每线程每秒的TPS开始变少,就意味着性能瓶颈已经出现了。但是瓶颈出现之后,并不是说服务器的处理能力(这里我们用TPS来描述)会下降,应该说TPS仍然会上升,在性能不断衰减的过程中,TPS就会达到上限**。
|
||||
|
||||
这也是前面我说的,性能瓶颈其实在最大TPS之前早就已经出现了。
|
||||
|
||||
那么我们是不是应该在性能衰减到最大TPS时就停止场景呢?这个不一定的哦。
|
||||
|
||||
因为停不停场景,取决于我们的场景目标,如果我们只是为了得到最大TPS,那确实可以停止场景了。但是,如果我们要扩大化性能瓶颈,也就是说为了让瓶颈更为明显,就完全不需要停止场景,只要不报错,就接着往上压,一直压到我们要说的下一个话题——响应时间变长,需要拆分。
|
||||
|
||||
## 响应时间的拆分
|
||||
|
||||
在性能分析中,响应时间的拆分通常是一个分析起点。因为在性能场景中,不管是什么原因,只要系统达到了瓶颈,再接着增加压力,肯定会导致响应时间的上升,直到超时为止。
|
||||
|
||||
在判断了瓶颈之后,我们需要找到问题出现在什么地方。在压力工具上看到的响应时间,都是经过了后端的每一个系统的。
|
||||
|
||||
那么,当响应时间变长,我们就要知道,它在哪个阶段时间变长了。
|
||||
|
||||
我们看下这张图。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/f7/0c/f76da16830ff8c41559537901f8d0a0c.jpg" alt="">
|
||||
|
||||
这应该是最简单的一个压力测试逻辑了。一个应用,一个DB,结果也拆分出了8个时间段,这还是在我没有加上压力工具自己所消耗的时间的情况下。
|
||||
|
||||
如果我们要分析压力工具中的响应时间,拆分的逻辑就是上面这个示意图。
|
||||
|
||||
但是在真实的场景中,基本上不是这样的。如果是内网,那基本上都是连在一个交换机上,所以通常是这样的:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/94/71/94c161f0082262de076233415e5e1671.png" alt="">
|
||||
|
||||
在这样的拓扑中,我们仍然可以拆出来t1到t8的时间。只是实际动手的时候,思路一定要清晰,时间拆分是从哪里到哪里,要画出来,不能混乱。
|
||||
|
||||
我们有很多手段可以进行时间的拆分,当然要看我们的应用支持哪一种。
|
||||
|
||||
如果我们是这样的架构,拆分时间应该是比较清楚的。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/a4/0d/a4552dfe28750a51eb34e5ed7d50230d.jpg" alt=""><br>
|
||||
首先我们需要查看Nginx上的时间。日志里就可以通过配置$request_time $upstream_response_time得到日志如下信息:
|
||||
|
||||
```
|
||||
14.131.17.129 - - [09/Dec/2019:08:08:09 +0000] "GET / HTTP/1.1" 200 25317 0.028 0.028
|
||||
|
||||
```
|
||||
|
||||
最后两列中,前面是请求时间的28ms,后面是后端响应时间的28ms。
|
||||
|
||||
同时,我们再到Tomcat上去看时间。
|
||||
|
||||
```
|
||||
172.18.0.1 - - [09/Dec/2019:08:08:09 +0000] "GET / HTTP/1.1" 200 25317 28 27 http-nio-8080-exec-1
|
||||
|
||||
```
|
||||
|
||||
请求时间消耗了28ms,响应时间消耗了27ms。
|
||||
|
||||
接着再来看一下前端的时间消耗。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/a6/04/a6821521f99df9f0a63df235b3395a04.png" alt="">
|
||||
|
||||
从这里可以看到,从发出请求到接收到第一个字节,即TTFB是55.01ms,内容下载用了11.75ms。从这就可以看得出Nginx基本上没消耗时间,因为它和Tomcat上的请求响应时间非常接近。
|
||||
|
||||
那么网络上的消耗时间怎么样呢?我看到有很多人用TTFB来描述网络的时间。先来说明一下,TTFB中显然包括了后端一系列处理和网络传输的时间。如下图所示。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/40/c8/401b25353a74784b41c7ed1f29d6e9c8.jpg" alt=""><br>
|
||||
下面的紫色点是指要接收的内容。上面的红色线就是TTFB。
|
||||
|
||||
如果接收完了呢?就是这个状态。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/cc/3c/ccdc306190e72f099c4757f2f9fd5e3c.jpg" alt=""><br>
|
||||
所以,我觉得用TTFB描述网络的健康状态并不合理。如果用Content Download来描述会更为合理。比如我们上面的这个例子中,那就是11.75ms下载了25317 Bytes的内容。
|
||||
|
||||
Tomcat上基本上是消耗了处理的所有时间,当然这中间也包括了MySQL花费的时间。而前端看到的其他时间就消耗在了网络中。
|
||||
|
||||
在这个例子中,主要说明了响应时间怎么一步步拆。当然,如果你是下面这种情况的话,再一个个拆就比较辛苦了,需要换另一种方式。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/40/c9/400e3191138d25ac195cae863093e4c9.jpg" alt="">
|
||||
|
||||
你肯定想知道每个系统消耗了多长时间,那么我们就需要链路监控工具来拆分时间了。比如像这样来拆分:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/8f/36/8fb9d1d502be932c8a34b6e50344d336.png" alt="">
|
||||
|
||||
从User开始,每个服务之间的调用时间,都需要看看时间消耗的监控。这就是时间拆分的一种方式。
|
||||
|
||||
其实不管我们用什么样的工具来监控,最终我们想得到的无非是每个环节消耗了多长时间。用日志也好,用链路监控工具也好,甚至抓包都可以。
|
||||
|
||||
当我们拆分到了某个环节之后,就有了下一步的动作:构建分析决策树。
|
||||
|
||||
## 构建分析决策树
|
||||
|
||||
关于分析决策树,我在很多场合也都有提及。
|
||||
|
||||
分析决策树,对性能测试分析人员实在是太重要了,是性能分析中不可或缺的一环。**它是对架构的梳理,是对系统的梳理,是对问题的梳理,是对查找证据链过程的梳理,是对分析思路的梳理。它起的是纵观全局,高屋建瓴的指导作用**。
|
||||
|
||||
性能做到了艺术的层级之后,分析决策树就是提炼出来的,可以触类旁通的方法论。
|
||||
|
||||
而我要在这里跟你讲的,就是这样的方法论。
|
||||
|
||||
应该说,所有的技术行业在面对自己的问题时,都需要有分析决策树。再广而推之的话,所有的问题都要有分析决策树来协助。
|
||||
|
||||
通过上面的几个步骤,我们就会知道时间消耗在了哪个节点上。那么之后呢?又当如何?
|
||||
|
||||
总要找到根本的原因才可以吧,我画了如下的分析决策图:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/aa/2b/aaa0c2e23aa5648a46d6a47b78c3c32b.jpg" alt="">
|
||||
|
||||
从压力工具中,只需要知道TPS、响应时间和错误率三条曲线,就可以明确判断瓶颈是否存在。再通过分段分层策略,结合监控平台、日志平台,或者其他的实时分析平台,知道架构中的哪个环节有问题,然后再根据更细化的架构图一一拆解下去。
|
||||
|
||||
我在这里,以数据库分析和操作系统分析举一下例子。
|
||||
|
||||
首先我们看一下数据库分析决策树。
|
||||
|
||||
比如针对RDBMS中的MySQL,我们就可以画一个如下的决策树:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/5b/27/5b9c8e2f05ee467ffc834dad86dcb927.png" alt="">
|
||||
|
||||
由于这里面的内容实在过多,无法一次性展现在这里。我举几个具体的例子给你说明一下。
|
||||
|
||||
MySQL中的索引统计信息有配置值,有状态值。我们要根据具体的结果来判断是否需要增加key_buffer_size值的大小。比如这种就无所谓了。
|
||||
|
||||
```
|
||||
Buffer used 3.00k of 8.00M %Used: 0.0004
|
||||
|
||||
```
|
||||
|
||||
从上面的数据可以看到,key buffer size就用到了4%,显然不用增加。
|
||||
|
||||
再比如,我们看到这样的数据:
|
||||
|
||||
```
|
||||
__Tables_______________________
|
||||
Open 2000 of 2000 %Cache: 100.00
|
||||
Opened 15.99M 4.1/s
|
||||
|
||||
```
|
||||
|
||||
这就明显有问题了。配置值为2000的Open Table Cache,已经被占满了。显然这里需要分析。但是,看到状态值达到配置值并不意味着我们需要赶紧加大配置值,而是要分析是否合理,再做相应的处理。比如说上面这个,Table确实打开得多,但是如果我们再对应看下这一条。
|
||||
|
||||
```
|
||||
Slow 2 s 6.21M 1.6/s
|
||||
|
||||
```
|
||||
|
||||
你是不是觉得应该先去处理慢SQL的问题了?
|
||||
|
||||
关于数据库的我们就不举更多的例子了。在这里只是为了告诉你,在分析决策树的创建过程中,有非常多的相互依赖关系。
|
||||
|
||||
然后我们再来看一下操作系统分析决策树,我在这里需要强调一下,操作系统的分析决策树,不可以绕过。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/79/1c/79420c5b099a09bc7b5120d98b968b1c.png" alt=""><br>
|
||||
如果你想到操作系统架构图就头大,那么这时候应该觉得有了希望。那就是我觉得操作系统上的问题判断是比较清晰的,所以基于此决策树,每个人都可以做到对操作系统中性能问题的证据链查找。
|
||||
|
||||
但是!对嘛,总得有个但是。
|
||||
|
||||
对操作系统的理解是个必然的前提。我看过很多人写的操作系统性能分析方面的书籍或资料,发现大部分人把描述计数器的数值当成性能分析。
|
||||
|
||||
怎么理解这句话呢?比如说<br>
|
||||
“CPU使用率在TPS上升的过程中,从10%增加到95%,超过了预期值。” “内存使用率达到99%,所以是瓶颈点。” “I/O使用率达到100%。” 等等。
|
||||
|
||||
像这样的描述,在我的性能团队中,一定会被骂回去重写。我要这些描述有什么用?我要的是为什么达到了这样的值,原因在哪?怎么解决?
|
||||
|
||||
就像分析决策树中所描述的那样,性能工程师要做的是一步步地细化分析,给出最终的原因。
|
||||
|
||||
有人说,如果按这个路子,似乎操作系统的分析并不复杂嘛。大概三五个命令就可以跳到代码层了。是的,对于操作来说,确实不多,但是对于判断来说,那就复杂了。举个例子来说明一下:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/62/23/62fe8e28939ba946aa409f643a826723.png" alt="">
|
||||
|
||||
看到这样的图,你是不是有种手足无措的感觉?中断能占40%,sy CPU也能占40%。这系统还用干业务的事吗?全干自己的事去了,可见操作系统有问题!你是不是要做这个判断了?
|
||||
|
||||
而实际情况是,这个主机上只有一个网卡队列,而请求量又比较大。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/dc/16/dc87f5b31b707be5fa115bd4e5f1b416.png" alt="">
|
||||
|
||||
所以要解决的是网卡队列的问题,至于怎么解决,那手段就多了。可以换个服务器,可以多加几个队列,可以多接几个节点......
|
||||
|
||||
以上只是给出几个性能分析过程中常见的决策树示例。在后续的分析过程实例中,我们将秉承着这种分析思路,一步步地走到瓶颈的面前。
|
||||
|
||||
## 场景的比对
|
||||
|
||||
为什么要写这一部分呢?因为我看到很多人对瓶颈的判断,并不那么精确,所以想写一下场景比对的建议。
|
||||
|
||||
其实简单来说,就一句话:当你觉得系统中哪个环节不行的时候, 又没能力分析它,你可以直接做该环节的增加。
|
||||
|
||||
举例来,我们现在有一个如下的架构:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/38/f1/387e513857efb2b5777a31f7ae92d4f1.jpg" alt=""><br>
|
||||
可以得到这样的结果:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/78/db/78e2dcb7bba43e27cbe715d2434c4bdb.png" alt="">
|
||||
|
||||
从TPS曲线中,我们可以明显看到系统是有瓶颈的,但是并不知道在哪里。鉴于系统架构如此简单,我们索性直接在某环节上加上一台服务器,变成这样:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/2b/ee/2b2bd4cd54f55481ea87e164ab18d4ee.jpg" alt=""><br>
|
||||
然后得到如下数据:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/a2/77/a2dd11b1143c09578fbedf6574f3b277.png" alt="">
|
||||
|
||||
哟,没好使!
|
||||
|
||||
怎么办?再接着加其他节点,我加了更多的JMeter机器。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/2b/ea/2bcaf3cdc7669efce857fcd5736f50ea.jpg" alt=""><br>
|
||||
再来看下结果:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/d5/7b/d59c58bd5a38efd9b397d5755330b27b.png" alt="">
|
||||
|
||||
真巧,TPS增加了!
|
||||
|
||||
看到了吧,这就是我说的场景比对。
|
||||
|
||||
当我们不知道系统中哪个环节存在性能瓶颈时,对架构并不复杂的系统来说,可以使用这样的手段,来做替换法,以快速定位问题。
|
||||
|
||||
## 总结
|
||||
|
||||
在这一篇中,我说到了瓶颈的精准判断、线程递增的策略、性能衰减的过程、响应时间的拆分、构建分析决策树以及场景的比对,这几个环节,是性能分析过程中非常重要的环节。
|
||||
|
||||
从我的经验上来说,这一篇文章可能是我工作十几年的精华所在了。而这里的每一个环节,又有非常多的细分,特别是构建分析决策树这一块,它需要太多的架构知识、系统知识、数据库知识等等。鉴于本文只是想起到一个提纲挈领的作用,所以无法展开描述,希望在后续的篇幅中,我们尽量细致拆解。
|
||||
|
||||
## 思考题
|
||||
|
||||
今天的内容虽然有点多,但总的来说,思路比较清晰,理解起来也比较容易。如果你认真学习了今天的内容,不妨思考两个问题,为什么线程递增过程不能断?构建分析决策树的关键是什么?
|
||||
|
||||
欢迎你在评论区写下你的思考,我会和你一起交流,也欢迎把这篇文章分享给你的朋友或者同事,一起交流一下。
|
||||
Reference in New Issue
Block a user