This commit is contained in:
louzefeng
2024-07-11 05:50:32 +00:00
parent bf99793fd0
commit d3828a7aee
6071 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,237 @@
<audio id="audio" title="01 | 性能工程:为什么很多性能测试人员无法对性能结果负责?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/74/b8/746a3c18e007a33fecb206149ca642b8.mp3"></audio>
你好,我是高楼。
今天是我们这节课的第一讲我要带给你一个全面的性能概念——RESAR性能工程它跟性能测试的逻辑不太一样具体哪儿不一样下面我就具体给你讲讲。另外在这个过程中我也会让你全面、系统地感知到性能工程都要做些什么工作。相信这节课不仅会改变你对性能的认知也能对你的性能项目全过程有一个指引。
## 要为性能负责,就不能局限在“测试”上
在[《性能测试实战30讲》](https://time.geekbang.org/column/intro/264)专栏中,我给出了性能测试的概念:
>
性能测试是针对系统的性能指标,建立性能测试模型,制定性能测试方案,制定监控策略,在场景条件之下执行性能场景,分析判断性能瓶颈并调优,最终得出性能结果来评估系统的性能指标是否满足既定值。
到现在,我仍然认为这是对“性能测试”最合理的描述。实际上,这一概念在出来之后引起了一些争论,主要在于:**性能测试的团队需要去做瓶颈定位和优化吗?**
我们先抛开概念本身,考虑这样一个问题:如果性能测试团队不做瓶颈定位和优化,那是否可以给出“上线后生产系统不会产生性能问题”这样的答案呢?
如果不能,那要这个性能测试团队有什么用?仅仅是找找初级的技术问题吗?这就像一个病人去医院看病,手术做了,药也吃了,一顿折腾后问医生:“我什么时候可以好呢?”要是医生说:“我也不知道!”你想想病人心里会是什么感受,有没有一种遇到庸医的感觉?
其实对应到性能测试中也是如此,我们的性能项目是有宏观目标的:
1. 找到系统中的性能瓶颈并优化掉;
1. 满足业务容量的要求,保障线上系统可以正常运行。
我建议你仔细看一下第二个目标,然后再想想我们刚才那个问题:性能测试的团队需要做瓶颈定位和优化吗?现在你是不是已经有答案了?当然是必须做呀!可是在当前的性能市场中,我看到很多性能团队连第一个目标都做不到,更别提第二个目标了。
带着这个问题的答案,我们再回到前面给出的“性能测试”概念。不知道你有没有意识到,对于“性能测试”来说,上面那个定义可能足够完整。但对于“性能”而言,是不是我们做完定义中的事情就完了呢?并没有。
因为从一个完整的性能工程来看,一个系统上线并经过正常的业务场景之后,我们还需要做一件事情:**把线上的性能数据拿回来,和性能测试过程中的数据做环比,看之前做的是否满足真实的业务场景。**而环比的内容就是我们的性能模型、性能指标等。
经过对比之后,如果没有误差,就说明这个性能测试项目做得非常好;如果有误差,那就需要我们修正误差,以便下一次做得更加贴合真实的系统。所以你看,从一个完整的性能活动的角度来讲,刚刚我们回顾的“性能测试”概念缺少了一个环境,就是**性能环比**。
可是,性能环比又实在不能称为是“测试”的工作内容(请注意,我说的是:性能环比不是“测试”的工作内容,并没有说它不是性能团队的工作内容)。
也正因为如此,一直以来,不管我们怎么对“测试”这个概念做扩充,不管是将它“左移”还是“右移”(我也没搞懂啥左移右移的,不就是干活吗?说那么文艺干吗?),不管是做“灰度”还是“白盒”,**只要一说是测试,它仍然会被限定在一个项目的某个时间段里**。就像无论是敏捷、精益,还是瀑布,只要在一个具体的项目中,大家还是会普遍认为先有业务需求,再有产品设计,然后才有接下来的架构设计、研发、测试、运维。
也许有人会说我可以不要测试直接上线。是的你可以这样做只要能承担上线的风险就好了。可是如果“测”和“不测”上线都会有相同的问题那这样的测试团队确实可以不要“拉出去祭旗”即可。如果在你的经验中“测”和“不测”出问题的比例是1:10那估计测试就不会被放弃。这是一个非常合理的逻辑。
我们要做好性能,**真正实现性能的那两个宏观目标,就不能只局限在“测试”上,不能将它当成是一个项目中的某一环,我们需要用“工程”的视角来看待“性能”这件事儿。**
## 为性能结果负责需要三方面支持
讲到这,我们还需要考虑一个问题:如果真的把测试只局限在项目的某个时间段内,那测试人员需不需要对整个线上负责呢?我想你心里应该有答案了,那就是不需要,因为测试人员被局限在一个环节里了。
不过,我相信有很多测试人员还是背了不少性能问题的锅。
如果出了问题后你仅仅是被领导骂几句,工作也没丢,那倒没什么关系。可如果你是做第三方测试的,你为线上负过责吗?你敢负责吗?在我的职业生涯中,有无数次听说某个系统上线后出了性能问题,导致千万级、亿级的经济损失。说真的,作为性能团队的人,我们还真负不起这个责。
作为性能测试人员,如果要对性能结果负起责任,我们至少需要以下三方面的支持。注意,“测试”自然是不能局限在项目的某个时间段内的,否则这没法弄。
- **技术细节**
首先,我们的技术细节需要做到和线上一致,比如说软硬件环境、网络架构、基础数据、测试场景、监控部署等等,这些我会在整个专栏中进行讲解。说到这,给你一个小提醒:在一个性能团队中,你自己的基础技能一定要能足够支撑起项目,这是一个前提。
关于技术细节要和线上一致的问题,有人可能会提到“线上全链路”。我想说的是,请不要看到一个概念就不理智地各种套用。在很多系统中,我们不可能在线上做这样的改造,原因很简单:如果你的全链路测试导致线上出了高级别事故,那把你一个团队废了都不解气。
- **工作范围**
要对整个系统性能负起责任,我们性能测试人员的工作范围就需要扩大,并且要**向前扩大到性能需求**。
有人说性能需求不就是性能测试人员定的吗这种无赖的锅我们可背不起。因为一个性能需求是由业务、架构、研发、测试、运维以及不懂技术的领导一起来定的。如果仅让测试人员来定性能需求在我遇到过的项目中有99.99%的机率会变成这个样子:这个性能项目仅仅是找找基本的技术瓶颈,有些性能团队甚至连技术瓶颈都找不到。
性能测试的工作范畴除了要向前扩大到性能需求外,还要再**向后扩大到运维过程**。我并不是在说性能团队的人要参与运维,而是我们要把运维过程中的数据拿回来做环比,然后迭代我们的性能实施过程。
- **工作权限**
当然,工作范畴扩大了,也要做到权责对等。
我遇到过很多公司,他们的性能团队都是处在职低言轻的位置上:对外,干不过架构、研发、运维;对内,技术没有自信;对上,领导说啥就是啥;对下,哦,下面没人,所以不用对下。
你想想,在这样的局面里,有时连个系统、数据库的操作权限都没有,还能对性能做什么优化?对于一个你连优化都没有权限的系统,如果它的性能出了问题,肯定也不是你该背的锅。
那什么是我们要的工作权限呢?有两种:**技术权限<strong><strong>和**</strong>指挥权限</strong>
技术权限很容易理解无非就是主机登录root、数据库DBA等权限。而指挥权限就是我们在需要什么人做什么事情的时候一定要能叫得动。比如你让运维查个生产数据要是运维只给你一个白眼这活就没法干了。所以我们需要什么数据会产生什么样的结果一定要环环相扣缺少了一个环节那就走不下去。
当然了,我们说要有指挥权限,并不是让你瞎指挥别人做不相干的事情,比如“来,研发给我捏个肩膀”“来,运维去给我买个咖啡”……这分明就是找揍。
我们讲了这么多,那到底性能测试应该如何干呢?这就要引出“性能工程”这个概念了。
## 什么是性能工程?
从“测试”到“工程”,看似是一个简单的描述变化,其实是完全不同的做事逻辑。
我先在这里下一个定义——RESAR性能工程。
我们平时说的性能工程是将IT中的各种技术应用到具体的性能项目中的过程。而我提到的**RESAR性能工程是对性能项目过程中的各个具体的动作做更详细的描述使之可以成为可以落地的具体实践。**
“RESAR性能工程”这个名字是我自己定义的你不用去网上搜索现在还搜不到。下面我会为你描述RESAR性能工程的过程。注意啊我们不讨论用什么样的研发模型比如敏捷、DevOps等因为这些都是过程的组织方式我们暂时把它们抛到脑后先来看看性能工程到底要干哪些事情。
- **业务需求**
从整个项目的生存周期角度来看,有了业务需求之后,我们就要开始分析可能出现性能问题的业务关键点,像业务路径、业务热点数据、秒杀业务、实时峰值业务、日结批量等。然后再创建出业务模型。
对于新系统来说,我们就算是拍脑袋也要给出业务模型;如果是已有系统的业务模型,那我们就可以通过统计生产业务量的方式来得到。
- **立项**
有了业务需求之后,技术项目就开始立项了。这时候需要具备性能架构思维的人介入到立项环节中,在技术选型、架构设计层面给予专业的意见,来规避以后可能出现的性能问题。
具体来讲这位拥有性能架构思维的人需要做高可用、可伸缩可扩展、负载均衡SLB、TCP层优化、DNS优化、CDN优化等与性能相关并且是架构该干的事情。再细化一下那就是各组件的线程池配置、连接池配置、超时配置、队列配置、压缩配置等细节。
有了这些内容之后,就开始做容量评估、容量模型建立、容量水位模拟等模型建立。
- **研发**
接着我们就到了研发环节。在这一环节中,当一个功能实现后,性能团队要做的是:列出每一个方法在没有任何压力的情况下,它们的执行时间以及对象消耗的内存,以便后续做容量场景时做相应的计算。
这是一个琐碎的工作,不过我们可以用一些工具进行整体分析,不用一个个看方法和对象。通常,这个步骤在学术界有一个更为笼统的名字,你应该听过,叫白盒测试。
其实,行业中大部分人做白盒测试也只是看看功能是不是正常,关注性能的人少之又少。而且,这个工作经常由研发工程师来做。这里我们不讨论自己测自己有什么问题,毕竟我们不能否定所有研发工程师的责任心。
如果我们只从普遍的项目周期来看的话,在资本家极尽压缩的手段之下,研发工程师在业务功能研发出来后,基本已经精疲力尽了,还能有时间干这些活吗?这时候,性能团队的存在就有了价值,就是把代码拿过来做性能分析。
所以,不要再说性能团队的人不懂开发是合理的,从性能工程的角度看,我们测试人员需要具备一定的技能。
- **测试**
有了完整的业务功能后,我们就到了测试环节,这时候性能测试工程师终于可以“正式”上场了。
在这一环节中,我们需要按照基准场景(单接口、单系统容量场景)、容量场景(峰值、日结、秒杀、日常等场景)、稳定性场景和异常场景的执行顺序,把前面所有和性能相关的工作都验证一遍。
关于异常场景是否要放在性能中的问题,其实一直都有着争论,不过我要说明一点,就是在我的概念中,只要是需要压力的场景,都可以放到性能中来做。
- **运维**
在系统上线运维之后,我们还需要把运维过程中产生的业务数据和性能监控数据,与前面做的性能场景结果数据做环比。如果比出了问题,那就修正性能过程,然后再从修正点接着往下做。
在[《性能测试实战30讲》](https://time.geekbang.org/column/intro/264)专栏里,我用这张图总结了性能测试的概念:
<img src="https://static001.geekbang.org/resource/image/36/5e/3647cddb54627aabcb0ca1e9e39f275e.jpg" alt="">
基于刚才讲的内容,我把它做一个变化:增加“业务分析和架构分析”、“环境准备”以及“生产运维”这三部分。
<img src="https://static001.geekbang.org/resource/image/15/80/155ff7d26a09a1865f473b720f4a7880.jpg" alt="">
现在这张图就完整描述了RESAR性能工程的过程。
明白了性能工程要做哪些事情后我们再来整体看一下“RESAR性能工程”。实施RESAR性能工程的要点是
- 通过分析业务逻辑和技术架构,创建性能模型,制定性能方案,准备应用环境,设计并实施性能部署监控;
- 实现符合真实业务逻辑的压力;
- 构建性能分析决策树,通过监控手段获取各组件的性能计数器;
- 分析计数器的数据查找出性能瓶颈的根本原因并优化;
- 通过环比生产环境的性能数据修正场景。
关于性能工程,你现在可能有很多疑问,下面我会着重给你讲一讲比较关键的几点。
## 一定的沟通成本是必要的
首先,还是来看我们这张性能工程的过程图。
<img src="https://static001.geekbang.org/resource/image/15/80/155ff7d26a09a1865f473b720f4a7880.jpg" alt="">
在图中,你可能觉得业务和架构分析、性能需求指标、性能模型和生产运维这几个环节看起来比较单薄。实际上,它们的工作内容并不少,并且有可能花费你很高的沟通和操作成本,消耗较长的项目时间。不过,这三个环节是可以与其他工作并行的。所以,项目整体的周期并不会有所增加。
有人看到这里或许会问:“这样的性能工作岂不是要消耗很大的精力?费时又费钱,要是看不到产出,那还值得吗?”如果你也有此困惑,不妨看看我们前面讨论的内容:
>
如果性能测试团队不做瓶颈定位和优化,那是否可以给出“上线后生产系统不会产生性能问题”这样的答案呢?
>
如果不能,那要这个性能测试团队有什么用?仅仅是找找初级的技术问题吗?这就像一个病人去医院看病,手术做了,药也吃了,一顿折腾后问医生:“我什么时候可以好呢?”要是医生说:“我也不知道!”你想想病人心里会是什么感受,有没有一种遇到庸医的感觉?
其实说到沟通和操作成本,可能是因为我遇到的工作环境大多比较“恶劣”,我经历过太多的江湖场面,所以非常清楚沟通的时间成本要远大于技术消耗的时间成本。不过,对于一个企业来说,这些工作一旦有了第一次流畅的执行后,往后几乎不会再消耗什么时间。而你如果把每天刷小视频和购物的时间拿来干这些活,也就足够了。
前段时间我给一个企业做咨询,从生产运维上拿数据回来做分析比对,只用了大概不到两个小时就把生产上的业务模型给弄出来了。不过,第一次做抽样的时间成本确实会高一些,因为我们可能需要搭建一些平台工具来支撑自己的想法。有了工具平台之后,后面的运维部分就比较简单了,不用太耗费精力。因为数据本来就在那里,性能团队只需要看一下那些数据。
不过在我遇到的客户场景中,经常可以看到性能团队的人想要个运维的监控数据都非常难。再加上如果你的技术又不怎么样,话说不出三句就让人怼得哑口无言,那别人就更会怀疑你要生产数据的潜在用心了。
所以,如果我刚接一个项目就看到这样的场景,那我肯定不会去问运维要数据来自己分析。我只会问他们要结果数据,并且我还会给他们定一个框,让他们就给框里的数据即可。
万一他们给不出来怎么办没关系你还记得小学生的绝招吗告诉老师呀经过沟通领导知道了这些数据的用途事情就好办了。如果运维觉得生产上的log都是关键的核心数据那也没关系让他们指定一个运维的人来天天陪着我就好了。在不断提供性能数据又反复加班的过程中他陪着你干一段时间之后就会主动把权限给你哈哈。
其实话说回来,在性能工作中不管涉及到了什么职位或是什么背景的人,你都要记住一点,作为性能团队的人,在你和别的团队沟通时,**一定要把问题提得精确具体**,把为什么要这样做,这样做的成本、好处,以及不这样做的坏处,都说明白就可以了。
这样做有什么必要吗?
我给你举个例子你想想我们为什么要用真实环境中的业务比例来做测试模型答案非常简单因为你不这样做的话测试出来的结果肯定不能回答生产容量的问题。如果一个业务的比例在生产上是10%而你在性能场景中定为20%,那就可能产生完全不一样的结果。
在性能项目中,有很多因为沟通不畅而导致的执行偏差,所以我们一定要搞清楚各方想表达的具体在执行层面如何操作,这个沟通过程非常非常重要。
## 性能工程由谁来推动?
我希望你能明白我在这里做的所有努力都是为了让性能有一个完整的环路。说到这里其实还有一个绝大的Bug那就是性能工程由谁来推动。
关于项目工程级的东西,一定不是一个职低言轻的人能干得动的,即使授权也照样不行,因为这需要很强的项目管理能力。而上层领导又不懂技术,甚至不能理解为什么弄个性能要这么大动干戈(要是遇到这种情况,你可以这样解释:如果不关心线上会不会“死”的话,那就不用大动干戈)。
所以,性能工程一定要由一个职高言重的人来推动。至于具体的工作内容,由性能实施的人来承接就可以了。
## “性能工程”不同于那些看似先进的概念
讲到这,你可能觉得有些概念与我所说的性能工程极为相似,比如全链路。我相信肯定有人会问,这时候是不是可以把全链路提到台面上来了?不是我贬低全链路的市场价值,在我们这个“说邮轮做筏子”的文化氛围里,很多企业都盯着大厂做事情,大厂做什么自己也跟着做什么,根本不仔细考虑这些事所产生的成本和代价。
其实大部分企业都消耗不起全链路的组织成本。如果仅仅做些技术改造,把链路改成旁路就叫做全链路,那实在是有些浅薄了。因为技术改造并不是关键的问题,关键在于你改造完了之后得跑起来。
**做线上全链路的目的,是为了通过使用生产环境中的架构、软硬件环境、数据、网络结构等等,来达到模拟真实业务压力场景的目标。**如果你做完了一连串的技术改造后结果只运行了30%的业务压力那就得不偿失了。如果你运行了100%甚至更高的业务压力,并且业务模型也符合生产的样子,那么恭喜你,这事做得非常有价值。
但是,很多系统不像互联网系统那样只有一个业务主流程。如果业务逻辑复杂度高,那出错的成本根本就不是一个企业能够承受的。我们不用脑袋考虑也能知道,这样不可能在线上做各种测试。所以,线上全链路这个思路,只对一些特定的业务场景有价值。而现在那些明明不适合却还要挤着脑袋往上凑的企业,再过几年自然会清醒下来。
至于DevOps在这里我不会展开说因为DevOps偏技术管理的角度。我也不想讨论什么左移、右移我也没搞懂啥左移、右移的不就是干活吗说那么文艺干嘛因为“左移”“右移”这个词特别像是主动抢别人的活有没有一个是该干的活一个是抢别人的活从职责划分上听着就不那么名正言顺。就像我之前听到有人说“全栈”这个词一样如今在我的生活中它也只是酒桌上说笑的谈资而已。
**在性能中,我不建议你用这些概念来规定边界,因为角度是不同的,而且也只有“工程”这个词符合我想表达的意思**。讲到这,我希望你能明白,性能工程就应该是针对一个系统生命周期的完整的工程级活动。
## 性能工程不是飘在天上的
另外我还想强调一点,请不要拿着“工程”的幌子干“测试”的事情,也不要把工程说得飘在天上。只跟别人说一大堆原理,却没有一个落地的过程,那是彻头彻尾地耍流氓。我见过太多所谓的“专家”,谈起理论时一套一套的,但在落地的时候,就灰溜溜地往后躲。
我曾经在一个项目上遇到一个专家,他刚到工作现场时,那状态别提有多牛了。等他扯了一通后,我淡淡地说了一句:“来,解决问题吧”。谁知这哥们回了一句:“百度上查呀!”当时我都有买枪的冲动了,还是那种带梭子的重机枪。
关于性能工程中的概念,我还是要尽量说明一下:请你注意,我给你讲的概念都不是枯燥且飘在空中的东西,它们一定是可以落地的。并且在后面的课程中,我会让你看见它们具体是怎样落地的。
## 总结
好,我们这节课就讲到这里,我给你总结一下。
鉴于在当前的性能市场中,大家都太把“测试”这个词当成重点,而从测试的角度出发,又解决不了线上会不会“死”的问题。所以我把性能提到“工程”的层面来解析。如果一个企业可以从“工程”角度来完整地规划性能过程,那必然会超出当前“性能测试”的范畴。而且,也只有从“工程”角度出发,才能够真正保障一个系统的业务正常运行。
说到这,我们把性能工程再次定义一下。很显然,这是我们这节课的重点。
性能工程是指,通过分析业务逻辑和技术架构,创建性能模型,制定性能方案,准备应用环境,设计并实施性能部署监控,实现符合真实业务逻辑的压力,通过监控手段获取各组件的性能计数器,分析计数器采集出的数据,查找出性能瓶颈的根本原因并优化,最后通过环比生产环境的性能数据修正场景。
## 课后作业
最后,我想请你思考两个问题:
1. 性能工程和全链路压测、DevOps等概念有什么区别
1. 描述下你理解的RESAR性能工程
欢迎你在留言区与我交流讨论。当然了,你也可以把这节课分享给你身边的朋友,他们的一些想法或许会让你有更大的收获。我们下节课见!
**关于课程读者群**
点击课程详情页的链接,扫描二维码,就可以加入我们这个课程的读者群哦,希望这里的交流与思维碰撞能帮助你取得更大的进步,期待你的到来~

View File

@@ -0,0 +1,183 @@
<audio id="audio" title="02 | 关键概念:性能指标和场景的确定" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/5b/ab/5b32bf93685aedca4db04f78d38db8ab.mp3"></audio>
你好,我是高楼。
上节课我们把性能从“测试”引到了“工程”级别。接下来,我们要理一理工程级别中几个重要的概念,包括:
- 性能需求指标;
- 性能场景;
- 性能分析决策树;
- 查找性能瓶颈证据链。
这些概念贯穿整个性能工程,有了它们,我们就不会在性能项目中迷失方向。为什么这么说呢?接下来的课程里,我会给你一一分析。
为了能让你更好地消化这些内容,我们把这几个概念分成三节课来详细讲解。今天这节课我们先来看“性能需求指标”和“性能场景”。
## 性能需求指标
说到性能需求,真是我从业十几年来性能职场辛酸的起点。因为我几乎没有见过精准明确的需求,很多时候性能需求都变成了一句空话。如果你对此感触不深,我们不妨来看两个反面教材。
**反面教材1**
<img src="https://static001.geekbang.org/resource/image/d3/9b/d3a3dcec9b1ca53ddb7c147128ac5c9b.jpg" alt="">
像这样的性能需求,基本上就是业务方的一种直观感觉,想看看单用户的操作响应,所以算不上是什么专业的性能测试需求。
不过你需要注意一点,这样的需求背后很容易埋着一个坑:列这个表的人可能想让系统在任何压力场景下都能达到这样的性能指标。那你就应该知道,明确性能需求是一个关键点,我们要明确在什么样的业务压力场景下要求这样的指标。在大压力的场景下,表格中所列的时间需求估计就实现不了了。因此,上面这张表格里的性能需求属于不合格的需求。
**反面教材2**
我们再来看看下面这个性能需求指标。
<img src="https://static001.geekbang.org/resource/image/12/72/123e11774777fd79f34839d9af84cc72.jpg" alt="">
这个需求看起来非常清晰,但仍然有一个问题,那就是不够细化。为什么这么说呢?
我给你举个例子这里面有一个指标值是“前端账户服务类交易≤5秒”我们知道账户交易有不少功能如果这里要求的是每个交易都不大于5秒的话那就过于宽泛了。其他的需求也有类似的问题。
而且表格里有一个指标是说“CPU平均使用率不高于80%”这个技术需求看似很具体可是我想问你是什么样的CPU使用率如果是us cpu的话那是不是使用率不高于80%就可以保证系统是好的呢还有没有其他的制约条件呢要不要再看看CPU队列呢
我给你这么一讲,你有没有觉得上面这些需求指标都没法用了?其实,在实际的工作场景中还有很多反面教材。
**那什么样的性能需求才是合理的呢?**这就需要我们从四种不同的性能场景入手,区别对待。
### **基准场景的性能需求指标**
我们先说下业务需求指标。我们可以列这样一个单业务性能指标的表格。
<img src="https://static001.geekbang.org/resource/image/eb/39/ebd3dcffde8f30a8413a30f332416e39.jpg" alt="">
(这是一个明显为基准测试场景列的指标,我在这里只是简单列了几个重要的参数,其他参数你可以自行组装。)
当然了你要是喜欢的话也可以把参数“标准方差”改为“响应时间的百分比”比如90%、95%、99%这样的值。如果我们在刚才的表格里加上这类限制,就会变成下面这样:
<img src="https://static001.geekbang.org/resource/image/53/13/53244e1fbc373029d08da82298a80613.jpg" alt="">
(注:这里的数据,我只是做一个示意展示,并不是说一定要满足这样的关系。)
对此,你知道为什么我们要定标准方差或者是响应时间百分比吗?因为对于性能来说,当平均值是一个比较优秀的值时,有可能会出现非常抖动的情况。要知道,“标准方差”和“响应时间百分比”的作用并不一样。前者是为了描述一条曲线的上下浮动范围有多大,而后者是为了查看曲线的上限在哪里。
平时我常看的是标准方差,因为对于性能来说,系统受到一些瞬间毛刺的影响时,会出现一些比较高的值。当然了,这也并不能说明系统不够稳定,我们需要分析原因才能知道为什么会有毛刺。下面我们通过几张图来感受一下标准方差对曲线影响的重要程度。
当标准方差比较小的时候标准方差约为2.5),示意图如下:
<img src="https://static001.geekbang.org/resource/image/08/b0/08589217246ac635552213b0415a7db0.jpg" alt="">
当标准方差较大时标准方差约为17.6),示意图如下:
<img src="https://static001.geekbang.org/resource/image/37/4b/37195f0dbb781d10a741009fba1d3c4b.jpg" alt="">
如果出现毛刺,示意图如下:
<img src="https://static001.geekbang.org/resource/image/4f/28/4ff42ccd0d85b6550bbd968e69e57a28.jpg" alt="">
(注:不知道你有没有发现,上面这张示意图其实是有问题的。因为显然上图是在固定的压力线程之下的,而中间有一个很高的毛刺,这就有问题了,如果全都是正确的事务,不应该出现这么高的毛刺。所以这种毛刺通常都是在压力过程中由事务错误导致的。
基准场景就是用这样的方式来限定业务需求指标的,那在容量场景中怎么办?我们需要添加什么参数来限定呢?
### **容量场景的性能需求指标**
**对于容量场景来说,最重要的就是业务比例,也就是我们经常说的业务模型。**同时,对于其他重要的性能参数也可以重新制定。示意如下:
<img src="https://static001.geekbang.org/resource/image/00/a3/00c4c6632d062719cf696b783f10eaa3.jpg" alt="">
(注:这里的数据,我只是做个示意展示,并不是说一定要满足这样的关系。)
你可以看到在这个容量场景中我们确定了业务比例也确定了总体TPS的需求指标再通过百分比我们就可以计算出每个业务的TPS目标。此外我还对响应时间做了限制。
从性能角度来看,这几个参数限制就足以定死一个场景了。从技术角度来说,这样的容量需求也是可测的。当然,容量场景也会有多个,这要取决于业务特性。
### **稳定性场景的性能需求指标**
关于这个场景的指标,我在后面的课程中会给你详细讲解。这里我主要强调两点:
1. 稳定性的时间长度要合理,也就是说要合理判断稳定性场景需要运行多长时间;
1. 稳定性使用的TPS量级要合理也就是说我们要合理判断稳定性场景应该用多大的压力执行。
上述是稳定性场景中非常重要的两个指标。
### **异常场景的性能需求指标**
针对该场景,你只需记住这个流程即可:**针对系统的架构,先分析异常场景中的需求点,再设计相应的案例来覆盖。**为什么要分析系统架构呢?因为在一个应用中,我们把功能测试完一遍之后,异常问题通常有两大类:其一是架构级的异常;其二是容量引起的性能异常。而对于架构级的异常,我们只能站在架构的角度进行分析。
描述完这些性能需求指标我们是不是就可以往下走了呢从性能技术的角度来说的确可以往下走了。但是你别忘了我们还没有描述用户级的指标。怎么办这里就涉及到并发度的计算了。因为如果没有并发度的计算我们就无法回答TPS和用户之间的关系。关于这一点我会在后面的实践部分中给你做操作级的详细解释。
## 性能场景
通常情况下,有了性能需求指标之后,我们需要把这些性能需求指标一一对应到场景中,看它们符合哪个类型。
可能有人看到这里会说:“我觉得全都有了呀。其实不是!在我的性能工程理念中,场景绝对不只有脚本和业务模型这么点内容。我在上一个专栏中已经描述了场景设计和执行,有两个重点:
- 场景分为四类(基准、容量、稳定性、异常);
- 执行过程中要保持连续递增。
在我们这个课程中,我要从工程级的角度把场景做更大的扩充。
你可能会想,场景是有多重要,至于吗?你可以把场景理解为是性能方案的落地,也是性能实施的核心,更是性能分析的起点......我大概能写出10个这样的句子来来说明“场景”的重要性。
下面这张图是性能场景所包含的内容。
<img src="https://static001.geekbang.org/resource/image/71/fb/719f56abcd4831a8f02e00b7fe42a5fb.jpg" alt="">
相信你可以感受到,在我的性能工程理念中,场景是一个复杂而宏大的概念。因为在我的工作中,只要场景跑起来,图中这些都是我要观察的内容。为什么?下面我就分别给你讲一讲,希望你能明白它们的重要性。
<li>
**性能脚本**:性能脚本只是场景中用来施压的部分,它记录了这个场景要做的是哪些事情,是接口级脚本、业务级脚本,还是用户级脚本?
</li>
<li>
**参数化数据**:这一点我在平时的培训中反复强调过多次,但是,仍然有很多人认为用少量的参数循环跑场景是合理的。这样的想法绝对是错的!因为如果严重的话,会直接导致结果不可用。
</li>
<li>
**监控策略**:请注意,在一开始的场景执行中,不要过度上监控工具,最好是先上全局监控工具。等有了问题之后,我们再重复执行场景,上定向监控工具。
</li>
<li>
**执行控制**:首先,我们得按“基准-容量-稳定性-异常”的逻辑执行;其次,在执行过程中要查看实时的数据曲线,并判断是停下来,还是继续,以及要分析哪些内容,以便我们清楚下一步要干什么事情。
</li>
<li>
**场景调整**:在这一步中我们需要明确很多东西,比如压力线程到底应该从多少开始,最大是多少;递增策略到底配置成什么样;要不要递减策略;持续时间是多长等等。
</li>
<li>
**软硬件环境**在场景执行时我们脑子里要有概念就是在这样的场景设计之下软硬件的表现应该是什么样子CPU、IO、内存、网络应该用多少线程池是否合理等等这些都要有经验上的判断和比对。
</li>
<li>
**基础数据/铺底数据**:不同的场景目标,对基础数据/铺底数据的要求是不一样的。而我们在性能场景中要求的基础数据/铺底数据就是和生产一致。
</li>
<li>
**挡板/Mock/第三方**:在场景中,对不可控的第三方一定要管控好,因为第三方的快慢会直接影响结果。这一步我们要根据场景的目标来。如果要测试的是真实生产逻辑,那就应该加上这一步;如果要测试的是,自己的系统有没有性能问题,那就可以屏蔽掉。但是在结果报告中,我们需要写明这个风险。
</li>
在我的性能理念中,上述这些都是必须存在的概念,场景有了这些内容后才像一个样子。在后面的课程里,我也将为你详细描述如何把它们应用到具体的项目中。
有了完美的场景之后,并不代表我们就可以得到完美的答案。因为还有更重要的事情在等着你,那就是做性能的分析。性能分析的逻辑要比场景设计复杂得多,大体来说主要有两个重点:
- 性能分析决策树;
- 性能瓶颈证据链。
我在前半生的职业生涯中,主要就是靠这两个思路支撑着我的工作,同时我也用这样的思路碾压过不少“马保国”们。在接下来的课程中,我会给你仔细讲解其中的精髓所在。
另外,还有两个关键点就是:构建性能分析决策树和判断性能瓶颈证据链,这些我也会在后面的课程中给你讲清楚。
## 总结
好,现在我们来总结一下这节课的内容。
从“性能测试”到“性能工程”的思路转换并不是一句话也不是画个图写个文章做个topic就可以尽述的。我们只有在工作中将上面说的每一步应用到具体的工作中去才是真正的工程。这也是我为你梳理性能概念的初衷。
我们再一起回顾下这节课的重点内容。
**性能需求指标**没有业务指标就没有技术指标而我们的工作就是让业务指标比如并发用户数、在线用户数等和技术指标比如CPU、IO等对应起来。在不同的性能场景中要定义好不同的性能需求指标有些是自己看的有些是给别人看的。
**性能场景**:其实性能场景真的不用有更多的分类了。我们讲的这四类场景(基准、容量、稳定性、异常)足够覆盖所有的性能执行过程。
## 课后作业
学完这节课后,请你再认真思考两个问题:
1. 性能场景为什么只分为四类就够了?
1. 你常见的性能需求指标都细化到了什么程度?
欢迎你在留言区写下你的思考和答案,和我交流讨论。如果你觉得这节课有收获,也欢迎把它分享给你身边的朋友,他们的一些想法或许会让你有更大的收获。我们下节课见!
**关于课程读者群**
点击课程详情页的链接,扫描二维码,就可以加入我们这个课程的读者群哦,希望这里的交流与思维碰撞能帮助你取得更大的进步,期待你的到来~

View File

@@ -0,0 +1,134 @@
<audio id="audio" title="03 | 核心分析逻辑:所有的性能分析,靠这七步都能搞定" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/8c/dd/8c754a89d0039b0716564dca6a895fdd.mp3"></audio>
你好,我是高楼。
我之前看过一些性能分析方法论比如SEI负载测试计划过程、RBI方法论、性能下降曲线分析法等等这些观点很多只是停留在概念和方法论的层面并没有具体的落地细节让人看了之后也不知道怎么进一步做下去。像这样的方法论在我看来完全没有必要存在。
在这里我也延伸一下,国外的一些理念在被翻译成中文之后,有很多只是停留在被知道、被了解的阶段,并没有被广泛应用过。像我们刚才提到的那些方法论,可能有很多从事性能行业的人都不知道。可见,这样的方法论不管好不好,都是没有受众基础的。而那些少数知道的人,也只是将这些理论翻译过来作为大帽子扣在某些文档上,但具体干起活来,该怎么干还怎么干。
如果我只是这样空泛地跟你说这些方法论不好使,那就是骂街了,作为文化人,还是得有理有据才行。下面我们就来看一段具体的内容。
你在任何一个搜索工具比如度娘、谷歌、360等等上搜“性能测试方法论”这几个关键字基本上都可以看到很多复制来复制去的内容。而这些内容基本上都是在描述一个测试的实施过程并且这些实施过程也都基本停留在测试的阶段。比如下面这几段关于“SEI负载测试计划过程”的描述内容可能有点长不过这不是我们这节课的重点你可以不用那么仔细去看
>
SEI load Testing Planning Process是一个关注于负载测试计划的方法其目标是产生“清晰、易理解、可验证的负载测试计划”。
>
SEI负载测试计划过程包括6个关注的区域目标、用户、用例、生产环境、测试环境和测试场景。
>
①生产环境与测试环境的不同:由于负载测试环境与实际的生产环境存在一定的差异,因此,在测试环境上对应用系统进行的负载测试结果很可能不能准确反映该应用系统在生产环境上的实际性能表现,为了规避这个风险,必须仔细设计测试环境。
>
②用户分析:用户是对被测应用系统性能表现最关注和受影响最大的对象,因此,必须通过对用户行为进行分析,依据用户行为模型建立用例和场景。
>
③用例:用例是用户使用某种顺序和操作方式对业务过程进行实现的过程,对负载测试来说,用例的作用主要在于分析和分解出关键的业务,判断每个业务发生的频度、业务出现性能问题的风险等。
从上面的描述可以看到这里面都是偏向“测试”执行过程的内容。这个理论的提出者是Mark McWhinney1992年他在SEI和John H. Baumert写了一个类似CMMI的内容《Software Measures and the Capability Maturity Model》。
在这份304页的白皮书里Mark McWhinney描述了四个级别的软件度量和成熟度模型分别是可重复级、可定义级、可管理级和可优化级其中描述的也都是过程、影响、成本、质量、稳定性这些内容。
像这样的定义本身没有问题但如果是像CMMI那样企业只是拿个证并不遵循它来做具体的项目那这个理论就没有意义了。
在性能行业中我们想要实际落地可是从SEI中又得不到具体的指引这才是问题。因为我们要有具体的性能容量、性能瓶颈的分析落地才能体现性能项目最终的价值。而这一部分的缺失使得很多性能从业人员没有可参考的成长路径。至于其他的性能方法论我就不再一一解析了。你如果有兴趣可以查一查。
这也是为什么在进入性能分析案例之前,我要和你先聊一下性能分析的核心逻辑。
在写《性能测试实战30讲》专栏中的[第6讲](https://time.geekbang.org/column/article/182912)时,我觉得已经把所有的核心分析逻辑都写完了,有一种呕心沥血的感觉,我也觉得自己不会再写分析逻辑了。可是在写这个专栏时,我还是觉得有些不够。
因为现在的性能工程师,最缺的就是分析思路。有很多人会各种工具,但是这些分析工具的数据拿出来应该如何组装成一串逻辑,又是很多人的难点。
如果从“测试”这个行业来看,性能分析的完整案例可以说非常少见。如果从运维或其他职位的角度来看的话,倒还是有一些的。但是纵观大部分的性能案例,都缺少一个提炼到更高一层的分析方法论。
所以,我觉得一个性能分析专栏,一定要有这样一讲内容来把分析逻辑说清楚。
不过,在写这一讲时,我没有之前那种呕心沥血的感觉了。因为我们这一讲的宗旨就是,**把性能分析思路给固定下来。**是的,你没有看错,我说的是“固定”下来,也就是说,这一讲之后,我们再也没有其他的分析思路了。
我把这个固定的分析思路称为“**RESAR性能分析七步法**”。请你注意这只是RESAR性能工程的一部分并不是整个RESAR性能工程。
## RESAR性能分析七步法
跟着RESAR性能工程理论我们的分析逻辑是这样的
<img src="https://static001.geekbang.org/resource/image/6f/ef/6fa5d7f028e913c78f115d37eba32eef.jpg" alt="">
#### **第一步:压力场景数据**。
在我看来压力工具提供的数据只有两个曲线最为重要一个是TPS你要是喜欢也可以叫其他名字像RPS、HPS、CPS之类纠结名称并不是我们的关键另一个是响应时间。
不管是什么压力工具,只要能给出这两个曲线即可,即便是你自己开发的多线程压力工具也无所谓。不管是线程、协程,只要可以根据业务逻辑发出相应的压力即可。
为什么说TPS和响应时间曲线最为重要那其他的曲线比如说吞吐量、点击率、错误率这些呢错误率是有错误的时候才需要看的这一点我想你应该不会有异议。而吞吐量、点击率之类的曲线也必然会和TPS曲线是相同的趋势所以我们不需要再单独分析。
因此在第一步我们只需要从压力场景中获取TPS和响应时间曲线就可以了。
#### **第二步:分析架构图**。
接着是分析架构图,这一步我们需要做的是,看压力流量的路径。这主要是为了看分析链路的前后关系。如果业务逻辑复杂,部署也复杂,那我们就可以分为业务路径和部署路径。如果不复杂,那画一个路径就够了。
#### **第三步:拆分响应时间**。
在这里,我要着重跟你强调一下,**在性能分析过程中,拆分响应时间是分析的关键起点。**有很多人在看到响应时间高的时候,总是不往下拆分就开始猜测系统的性能瓶颈在哪里。如果你也是这样,这种思路你一定要转换过来,不要总是在现象上纠结。
#### **第四步:全局监控分析**。
话说现在很多看似拥有全局监控能力的工具平台,实际上还是会缺失一些计数器。所以,我们一定要根据性能分析决策树,来补全性能计数器。如果获取这些计数器,在当前的工具平台上实在有困难,那就通过其他的工具或命令来补充,这一点你要特别注意。
之前我给一个银行客户分析问题的时候,他们说各个层面的监控数据都有。但实际情况却是,与问题相关的计数器,他们是缺失的。这样的情况其实很普遍,很多公司往往只关注大层面的覆盖,忽视了具体计数器的完备。
“全局监控分析”‘这一步有个关键,就是**你要对你所看到的计数器有足够的了解**。如果你看了数据之后,没有任何反应,那就说明你还没有达到分析的能力。这个时候,你要么就是来看专栏,要么就是去看书,要么就是去查度娘(虽然度娘在这个时候也不好使),要么就是放弃。
那我们怎么知道一个全局计数器有没有问题呢?这就需要功底了,这些就是我经常说的计算机基础知识。性能分析的范围很大,不见得与它相关的所有知识的头上都会标着“性能”两个字。
经常会有人问GC频率达到多少是合理的这就是很难回答的问题。只要GC不影响系统容量那就是可以的。所以我们得先看GC和系统容量曲线之间的关联关系然后再做判断。
在性能分析中,没有哪个计数器可以直接跳出来告诉我们说“我有病!”,只能靠我们自己去判断它有没有病。
#### **第五步:定向监控分析**。
看了全局监控计数器之后我们通过判断分析知道哪个方向上有问题后才去做定向的监控。千万不要一开始就弄什么代码层分析、具体参数调整、SQL调整啥的。不仅乱而且不一定见成效。
在“定向监控分析”这一步有个关键判断,就是**能不能和上面的全局监控计数器对应**。当我们想找一个栈的时候要知道为什么要去找栈当我们要判断IO参数有问题时也要知道为什么要去找IO参数。
这样一来前后的逻辑关系就形成了我一直在RESAR性能工程中强调的一个词——证据链。
#### **第六步:判断性能瓶颈点**。
有了证据链就一定要来到性能瓶颈点的判断过程。比如说我们在栈中判断有没有锁的存在那至少你要在栈中找到这个锁有哪些线程在等待哪个线程持有。再比如说我们要判断一个SQL慢那至少你要把SQL的执行过程拿出来看到底是哪一步有问题。
有了对性能瓶颈的判断,再往下走就是要找到解决方案。
#### **第七步:确定解决方案**。
其实知道瓶颈点在哪里也并不一定知道有什么解决方案。就像有人看到了栈中有锁但也不知道怎么解锁有人知道SQL慢但也不知道如何优化SQL一样。不过这一步是性能项目体现价值的关键点。不管前面做得有多么辛苦给出解决方案总是我们性能人员的重点。
上述就是RESAR性能分析七步法它在每个性能分析的案例中都会被使用。在具体的案例中我们可能会选择其中的几步来做。当然每个案例都走七步也是完全可以的。只是在我们分析的过程中如果已经有了明确的问题点就**不用再往回分析**了。
比如说,如果我们已经知道了问题点,直接定向监控分析就可以了,不用再走第四步。还有就是,如果性能瓶颈不会导致响应时间长,而是出现其他的问题,可能就不需要走第三步。这些内容你将在后面课程的案例中看到具体的应用。
## 总结
我们这节课讲的性能分析的核心逻辑是RESAR性能工程中具体的性能瓶颈分析指导。没有它就没有分析的具体落地步骤。但是如果在落地时不遵循这个核心逻辑它也就没有价值了。
在这七步法中,会涉及到对应的知识体系,像在构建性能分析决策树、查找性能瓶颈证据链时,我们就需要强大的技术基础知识做支撑。如果一个人不具备全部的基础知识也没关系,可以组织一个团队共同来做这件事情。
对于我来说RESAR性能分析七步法是我做任何一个性能瓶颈定位时必须要依赖的逻辑它帮助我解决了很多以前没有遇到过的问题。如果你想应用这个过程那就请记住我一直强调的一句话在性能分析中你只需要知道下一步做什么就可以了我们终会找到瓶颈的具体原因。
## 课后作业
最后,请你思考两个问题:
1. 为什么在性能项目中需要RESAR性能分析七步法
1. 在你之前做过的调优案例中,用的是什么样的分析逻辑?
欢迎你在留言区写下你的思考和答案,和我交流讨论。如果你觉得这节课有收获,也欢迎把它分享给你身边的朋友,他们的一些想法或许会让你有更大的收获。我们下节课见!
**关于课程读者群**
点击课程详情页的链接,扫描二维码,就可以加入我们这个课程的读者群哦,希望这里的交流与思维碰撞能帮助你取得更大的进步,期待你的到来~

View File

@@ -0,0 +1,269 @@
<audio id="audio" title="04 | 如何构建性能分析决策树和查找瓶颈证据链?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/bd/7a/bdb2b1b8645d9465e5805bdd0d78b47a.mp3"></audio>
你好,我是高楼。
上节课我给你讲了一个完整且固定的性能分析流程——RESAR性能分析七步法它可以应用在任何性能分析案例中。在这个分析流程中有两个关键的技术和思路分别是性能分析决策树和性能瓶颈证据链。这也是我们在[02讲](https://time.geekbang.org/column/article/355019)中提到的,贯穿整个性能工程的两个重要概念。
今天这节课,我们一起来看看怎么一步步构建性能分析决策树和查找性能瓶颈证据链。
## 如何构建性能分析决策树?
实际上,性能分析决策树在性能监控设计和性能瓶颈分析时都会被使用,并且在性能瓶颈分析时,**我们必须要有决策树的思路**。所以,这是我一定要给你描述的步骤。在后面课程的分析中,我们也会大量地用到“性能分析决策树”这个词。
首先,什么是性能分析决策树呢?
>
性能分析决策树是包括了系统架构中所有技术组件、所有组件中的模块以及模块对应计数器的完整的结构化树状图。
在这句话中,有三个重要的层级,分别是组件、模块和计数器:
<img src="https://static001.geekbang.org/resource/image/31/27/3153f75ce3b9691d49bec6024e23c927.jpg" alt="">
在后面的课程中,我也会频繁使用这三个关键词。
不过这个关于“性能分析决策树”的定义虽然很合理但还是会让人感觉抓不住重点就像看了哲学语句一样。但是IT技术并不是哲学所以我们还要把它细化下去。
构建性能分析决策树是我们了解一个系统非常关键的环节总体来看它分为4个步骤。
**第一步:根据系统的架构,罗列出整个系统架构中的组件。**
在我们这个课程搭建的系统中,整体架构的组件是这样的:
<img src="https://static001.geekbang.org/resource/image/b7/22/b764098c8f09498805d387d3acbaf422.jpg" alt="">
对应上面这张图,我们就能罗列出该系统的所有组件,如下:
<img src="https://static001.geekbang.org/resource/image/af/d5/af2fdb53f02d40058dcd50504a21fbd5.jpg" alt="">
**第二步:深入细化组件中的每一个重要的模块。**
由于我们这个系统中的组件太多,我们先选择其中一个比较重要的组件——操作系统,来做示例。因为操作系统是性能分析中非常重要的一个环节,几乎所有的问题都会体现到操作系统的计数器上。至于其他的组件,你可以根据我说的流程自行确定一下。
根据操作系统的特性,我们先画出它的重要模块:
<img src="https://static001.geekbang.org/resource/image/6d/e1/6d1c9ae3b558d6e51885b91f1f6eb6e1.jpg" alt="">
我在图中画了六个模块其中一个是Swap。Swap的存在是为了让系统在没有内存可用的时候可以用硬盘来做内存的交换分区。当Swap被用到时其实就说明性能已经有了问题。所以一般不建议在性能项目中使用Swap我们应该在使用Swap之前就把性能问题解决掉。不过在生产环境中如果我们被逼无奈也只能把Swap打开了。
至于图中其他几个模块,基本上是我们在性能分析中必须要看的内容。
**第三步:列出模块对应的计数器。**
在罗列计数器的时候,我们要注意把**每个模块重要的计数器都囊括进来,千万不能漏掉重要的第一级计数器**,如果漏掉的话,有些数据可能就需要重新跑了。
现在我们来看其中一个重要的模块——CPU。我们可以通过top命令查看到CPU的几个重要的计数器
```
[root@k8s-worker-8 ~]# top
top - 00:38:51 up 28 days, 4:27, 3 users, load average: 78.07, 62.23, 39.14
Tasks: 275 total, 17 running, 257 sleeping, 1 stopped, 0 zombie
%Cpu0 : 4.2 us, 95.4 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.4 st
%Cpu1 : 1.8 us, 98.2 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu2 : 2.1 us, 97.9 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu3 : 1.0 us, 99.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
```
可以看到top命令中有九个计数器分别是us/sy/ni/id/wa/hi/si/st/load average。前8个是CPU的计数器这是毋庸置疑的。那最后一个load average是什么呢
在搜索引擎上我们经常能看到一些关于load average的笼统描述。有人说load average高过CPU就说明系统负载高也有人说load average和CPU并没有直接的关系观点不一。
load average作为CPU一个非常重要的性能计数器我们在用它做判断时如果不能给出非常明确的判断方向那就有大问题了。所以我要给你好好描述一下。
>
load average是1m/5m/15m内的可运行状态和不可中断状态的平均进程数。
这个说法非常对,但中规中矩,而且不是非常具体。
对于“可运行状态”我们比较容易理解。从上面代码块中的数据可以看到tasks中有一个Running状态的任务数。不过可运行状态不只是它还有一些万事俱备只差CPU的情况。也就是说tasks中的Running状态的任务数与load average的值之间并不是直接的等价关系。
同样在vmstat中我们也能看到运行的任务数。在vmstat的proc列有两个参数r 和 b。其中r 是指正在运行状态和等待运行状态的进程在man手册中是这样描述的
```
r: The number of runnable processes (running or waiting for run time).
```
对于不可中断状态我们经常见到的就是等IO。当然也不止是等IO内存交换也会在这个状态里这种等IO的情况会体现在vmstat中proc下面的b列。下面这个计数器就是vmstat的proc的b列的说明。
```
b: The number of processes in uninterruptible sleep.
```
所以我们可以看到,**load average实际上就是vmstat中proc列的r与b之和。**
其实CPU不止有us/sy/ni/id/wa/hi/si/st/load average这九个计数器它还有两个计数器藏在mpstat中分别是%guest和%gnice。
```
[root@k8s-worker-8 ~]# mpstat -P ALL 2
Linux 3.10.0-1127.el7.x86_64 (k8s-worker-8) 2021年02月15日 _x86_64_ (4 CPU)
14时00分36秒 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
14时00分38秒 all 5.13 0.00 3.21 0.00 0.00 0.26 0.00 0.00 0.00 91.40
14时00分38秒 0 4.62 0.00 2.56 0.00 0.00 0.00 0.00 0.00 0.00 92.82
14时00分38秒 1 4.57 0.00 3.05 0.00 0.00 0.00 0.00 0.00 0.00 92.39
14时00分38秒 2 5.70 0.00 3.63 0.00 0.00 0.00 0.00 0.00 0.00 90.67
14时00分38秒 3 5.70 0.00 4.66 0.00 0.00 0.00 0.00 0.00 0.00 89.64
```
从下面这段描述中可以看到,如果在宿主机上看%guest和%gnice这两个参数是比较有意义的因为它可以说明Guest虚拟机消耗CPU的比例。如果你的宿主机上有多个虚拟机你就可以通过这两个参数值来看虚拟机是不是消耗CPU太多然后通过查进程的方式看看具体是哪一个虚拟机消耗得多。
```
%guest Show the percentage of time spent by the CPU or CPUs to run a virtual processor.
%gnice Show the percentage of time spent by the CPU or CPUs to run a niced guest.
```
所以在Linux操作系统中如果是宿主机我们就需要看11个计数器。如果是虚拟机的话看9个计数器图中前9个就可以了
<img src="https://static001.geekbang.org/resource/image/80/0f/809cef070c881a5d7ef4e31cb8f24f0f.jpg" alt="">
讲到这里我们已经罗列出与CPU相关的所有计数器了。我们前面提到要根据Linux操作系统中的各个模块把相应的计数器全都罗列出来。所以其他模块的计数器我们也需要像这样完整地找出来。
当我们把Linux操作系统所有的关键一级计数器找完之后就会得到这样一张图
<img src="https://static001.geekbang.org/resource/image/53/50/53f3f70b3fe256549d9b10d13d599050.jpg" alt="">
请你注意,这些计数器里,有一些会比较关键,我根据自己的经验,把重要的计数器都标红了。当然,如果你对操作系统有足够的理解,也可以从不同的角度,用不同的思路,列出自己的图。要知道,罗列计数器只是一个体力活,只要你愿意,就能列出来。
**第四步:画出计数器之间的相关性。**
从上面的图可以看到,尽管我们列出了很多计数器,但是这些计数器之间的关系是什么,我们还不清楚。
在分析的时候,由于我们要根据相应的计数器,来判断问题的方向(有时候一个计数器并不足以支撑我们作出判断,那我们就需要多个计数器共同判断)。所以,我们要画出这些计数器之间的关系,这一步非常重要。
我根据自己的理解画出了Linux操作系统中计数器之间的关系如下所示
<img src="https://static001.geekbang.org/resource/image/32/df/32a9714095aa2ff0c8002ee7fa2da7df.jpg" alt="">
如果线画得太多,看起来会比较混乱,所以我只画出了几个最重要的关键相关性。
至此我们就把Linux操作系统的性能分析决策树画完了计数器也覆盖全了。不过工作还没有结束因为我们还需要找到合适的监控工具来收集这些计数器的实时数据。
### 收集计数器的实时数据
请你注意在收集计数器的实时数据时可能不是一个监控工具就可以完全覆盖所有的计数器的。所以在分析的时候我们一定要清楚监控工具的局限在哪里。如果一个工具无法监控到全部的计数器那就必须用多个工具相互补充比如说对于Linux操作系统的监控现在我们最常用的监控工具就是prometheus+grafana+node_exporter像这样
<img src="https://static001.geekbang.org/resource/image/c9/11/c9c577792a0ce67828223ea00a0c2211.png" alt=""><img src="https://static001.geekbang.org/resource/image/e4/36/e4fe7316655998ab94d73e4ea08f5436.png" alt="">
这是我们经常用的监控Linux操作系统的模板。那这个模板的数据全不全呢其实一对比就能发现这个模板虽然可以覆盖大部分Linux操作系统的性能计数器但是并不全比如说网络的队列、内存的软/硬错误等,这些就没有覆盖到。
因此,**我们在使用监控工具之前,一定要把性能分析决策树中的计数器,与监控工具中的计数器做对比,缺什么,我们就要在分析时用其他的监控工具或是命令来做补充。**
请你记住一点,**用什么监控工具并不重要,有没有监控到全部的计数器才重要**。即便我们没有任何的监控工具,要是只敲命令也能监控到全部计数器的话,也是可以的。所以,我希望你不要迷信工具。
到这里,整个性能分析决策树还没有结束。因为在这个系统的架构中还有其他的技术组件,而我们的任务就是把这些技术组件,都按照我们前面讲的那四个步骤,画出相应的性能分析决策树,最终形成一张完整的大图。
在我们这个系统中,如果画出全部的技术组件和模块的话,就会看到下面这张图:
<img src="https://static001.geekbang.org/resource/image/25/4d/25de97b84a0f8835dd3426b23bcd6a4d.jpg" alt="">
整个图我没有全部展开,要是展开的话就太大了,会完全看不到末端的计数器。不过你放心,在后面课程的分析案例中,我会让你看到如何应用这个性能分析决策树来做相应的问题分析。
讲到这里,我就把性能分析决策树完整地给你描述完了,步骤也列清楚了。古人有云:授人以鱼不如授人以渔。所以,我希望你看到这些步骤之后,可以画出你自己项目中完整的性能分析决策树。
我还要强调一点,这里我们只列出了第一级的性能计数器。如果第一级计数器有问题,而我们还不能判断出问题的原因,那就需要接着找第二级、第三级、第四级.....关于怎么找更深层级的性能计数器,我会在接下来证据链的部分给你讲解。
不过,在我们一开始梳理性能分析决策树时,没必要把所有层级的性能计数器都列出来。因为可能我们整个项目做完了,都没有用到全部的计数器,全列出来容易浪费时间。只有我们看懂了第一级的计数器,并且判断出问题的方向,才有可能需要看更深层的计数器。
所以,**你要注意,理解每个计数器的含义才是至关重要的**。如果不理解计数器的含义,也不知道如何运用计数器,那我们就不可能知道怎么去做分析。
有了性能分析决策树之后,我们如何应用它呢?接下来,就不得不讲一讲性能瓶颈的证据链了。
## 怎么查找性能瓶颈证据链?
在每次做培训或者性能分析时,我都会强调,性能分析中有一个非常关键的词,那就是“证据链”。
如果性能分析没有证据链,那么分析思路就是跳跃的。通俗点讲,就是蒙,根据经验蒙,根据资料蒙。这种跳跃的分析思路是非常容易出错的。所以,我们在分析性能瓶颈时,一定要有理有据、顺藤摸瓜。
那具体怎么来判断呢?接下来我会通过一个例子给你讲解。
### 全局监控分析
在进入这个例子之前,我需要跟你强调一点,在性能分析中,监控分析可以分为两个部分:全局监控分析和定向监控分析。全局监控分析是指将整个架构中具有概括性的计数器都分析一遍。也**只有从全局监控计数器,我们才能看到性能问题的第一层现象**。
比如说如果我们想找到哪一行代码有消耗CPU的问题首先我们是不知道具体是哪一行代码的但是在CPU计数器上会体现出CPU使用率高的现象。而全局监控就是为了查看CPU消耗是不是比较高当我们看到CPU消耗高的时候再往下找是哪一行代码消耗CPU比较高这就用到了定向监控分析的思路。
所以在性能分析的过程中,我通常会分为全局监控分析和定向监控分析两个阶段。而全局监控分析既可以用监控平台,也可以用命令。
在我之前做过的一个项目中有一个主机有24颗CPU我在场景执行过程中看到了这样的数据
<img src="https://static001.geekbang.org/resource/image/13/e1/13a47c8ce29f91b791d4f1e5ffeeb4e1.png" alt="">
这就是我们前面提到的性能分析决策树中CPU监控的具体命令。所以我们接下来的分析逻辑就是**根据性能瓶颈的分析应用,选择相应的监控手段,覆盖性能分析决策树中<strong><strong>需要监控的**</strong>计数器,**<strong>然后**</strong>再进一步细化分析。</strong>
在上面这张图中我们看到所有CPU的%us使用率并没有很高%id也不小还有一些剩余。但是%si软中断这一项唯独第22颗CPU的%si有21.4%之高。那这个软中断合理不合理呢?
有人可能会说,这也没有太高嘛,能有什么问题?如果我们只看%si平均值的话可能确实发现不了问题的存在。但如果仔细看图中更详细的数据就会有不一样的结论了这也是为什么我们要把每颗CPU的使用率都先列出来的原因。
我们说当一个应用跑着的时候如果应用代码消耗了很多CPU那%us的使用率应该会变高但是在上面我们看到的并不是%us高。并且在合理的情况下每个CPU都应该被使用上也就是说这些CPU的使用率应该是均衡的。
但是在这个图中我们看到只有CPU 22的%si使用率比较高为21.4%。并且软中断(%si只使用了24颗CPU中的一颗。这个软中断显然是不合理的。
### 定向监控分析
那既然软中断不合理我们自然是要知道这个软中断到底中断到哪里去了为什么只中断到一颗CPU上。所以我们要去查一下软中断的数据。
在Linux操作系统中有不少工具可以查看软中断其中一个重要的工具就是/proc/softirqs。这个文件记录了软中断的数据。在我们这个例子中因为有24颗CPU数据看起来实在比较长。所以我先把一些CPU数据过滤掉了只留下图中这些数据来分析。
<img src="https://static001.geekbang.org/resource/image/9e/96/9ed28fded9b2329db013d6100eef1796.png" alt="">
在这张图中我标注出了CPU 22和它对应的模块名NET_RX。你可能会奇怪怎么一下子就找到了这个模块呢这是因为CPU 22的使用率最高在它上面产生的中断数自然要比其他CPU高得多。
由于 /proc/softirqs文件中的各个计数器都是累加值其他模块在各个CPU上的累加值比例都没有太大的差别只有NET_RX模块在不同CPU上的计数值差别很大。所以我们可以作出这样的判断CPU 22的使用率高是因为NET_RX。
我们看“NET_RX”这个名字就能知道这个模块的意思是网络接收数据。那在网络数据接收的过程中什么东西会导致网络的中断只中断在一颗CPU上呢
我们知道,网络的接收是靠队列来缓存数据的,所以我们接下来得去查一下网络接收的队列有多少个。我们可以通过/sys/class/net/&lt;网卡名&gt;/queues/路径,查看到这个网络队列:<br>
<img src="https://static001.geekbang.org/resource/image/a7/92/a724bcd6a30c2ba0fe5d7cfe09eef092.png" alt="">
不难看出RX队列确实只有一个这也就意味着所有的网络接收数据都得走这一个队列。既然如此那自然不可能用到更多的CPU只能用一颗了。
讲到这里我要多说明一点因为我们这节课重在讲解分析的逻辑所以我在这里就不做更加细致的分析了。如果你要想更深入地理解网络中断逻辑可以去翻一下Linux源码看看net_rx_action函数。不过归根到底中断在系统层的调用都是do_softirqs函数所以当我们用perf top -g命令查看CPU热点的时候你同样也可以看到上面我所描述的逻辑。
既然我们知道了网络接收队列只有一个那上述问题的解决思路自然也就出来了多增加几个队列让更多的CPU来做中断的事情。因为网络中断是为了把数据从网卡向TCP层传输所以队列一旦变多了传输速度也会变得快一些。
所以,我们的解决方案就是增加队列:
<img src="https://static001.geekbang.org/resource/image/29/4f/29b666e6fda238956313dc9a011daf4f.png" alt="">
在我们这个例子中我把队列增加到了8个这样网络接收数据就会用到8颗CPU。如果你想用更多的CPU也可以这里我们有24颗CPU那就可以设置24个队列。如果你用的是虚拟机对于这个改动你可以在KVM的XML参数中增加一个队列参数来实现如果你用的是物理机那你就只能换网卡了。
现在我们把整个分析逻辑都理清楚了,下面就按照这个逻辑把对应的证据链画一下:
<img src="https://static001.geekbang.org/resource/image/77/85/7776f9abc8bdd4a004eca72cf446b285.jpg" alt="">
根据图中展示的逻辑,当我们看到%si软中断高时就去查看cat/proc/interrupts目录。其实对于这个软中断有两个目录可以体现出来一个是cat/proc/interrupts另一个是cat/proc/softirqs。前者不仅包括软中断还包括硬中断如果我们看到软中断高其实直接看cat/proc/softirqs就可以了。
紧接着,我们要找到对应的模块,然后再找到这个模块的实现原理,最后我们给出相应的解决方案。
这样一来,这个问题的完整证据链就找到了。
相信你通过这个例子可以看出,性能瓶颈的证据链其实就是,性能分析决策树在具体应用过程中完整的分析逻辑的记录。
请你注意我们一开始并不会直接去看cat/proc/softirqs的内容因为这个太定向、太具体了。我们一定要先看全局的数据然后再一步一步往下去找这样才是合理的。不难发现我们从全局监控分析拿到的数据和从定向监控分析拿到的数据是不一样的因为它们是不同的角度这一点你也要格外注意。
## 总结
这节课和上节课一起,我把整个分析逻辑总结为:**RESAR性能分析七步法**,这是性能分析方法论中最重要的核心逻辑。不过,这些内容“孤篇盖全唐”的可能性很小,毕竟性能分析涉及到的所有细节无法在短短两节课里尽述。
所以,我把我认为最重要的部分都给你描述出来了,当你在实际应用时,可以按照这个思路,实现你的性能分析决策树和性能瓶颈证据链。前提是,你要理解你的系统,理解你的架构,并且要理解我给你讲的分析逻辑。
在这节课中,我为你讲解了两个重要的内容:性能分析决策树的构建,以及性能瓶颈证据链的查找。这是我们在每一个性能问题的分析过程中,都必须经历的。只有把决策树和证据链具体落地,我们才能在性能分析中无往不利。
## 课后作业
最后,请你思考一下:
1. 如何构建你自己的性能分析决策树?
1. 举一个你做过的性能分析中有完整证据链的案例。
欢迎你在留言区与我交流讨论。当然了,你也可以把这节课分享给你身边的朋友,他们的一些想法或许会让你有更大的收获。我们下节课见!
**关于课程读者群**
点击课程详情页的链接,扫描二维码,就可以加入我们这个课程的读者群哦,希望这里的交流与思维碰撞能帮助你取得更大的进步,期待你的到来~