快速拎清不同种类的性能测试

快速拎清不同种类的性能测试

作者/小田圭二等

日本Oracle株式会社咨询部门经理。在解决性能问题方面有着丰富的经验,著有《图解OS、存储、网络:DB的内部机制》(絵で見てわかるOS/ストレージ/ネットワーク~データベースはこう使っている)、《图解Oracle的机制》(絵で見てわかるOracleの仕組み)等多部著作。

在处理性能问题方面,虽然调优是主角,但是“性能测试”是不可或缺的。要让调优顺利进行下去,最重要的工作就是通过测试来验证。不过,如果将调优结果直接在生产环境中验证,会有一定风险,因此通常是在验证环境中获得性能测试的结果,来验证调优的成果。在通往调优专家或性能专家的道路上,性能测试可以说是最重要的要素。

项目工程中的性能测试

在系统开发项目工程中,性能测试实际上主要在系统测试阶段执行。这是因为性能测试原则上是为了确认“系统在生产环境中运行时是否会有性能上的问题”,所以它是在完成集成测试后,确认系统能在生产环境中正常运行之后的阶段执行的。

即便如此,如果认为在进入系统测试阶段之前不需要考虑性能测试,那就错了。

测试的实施周期

在通常的开发、搭建项目的各个阶段,性能测试有几个变种。

作为判断性能的基准,最重要的测试就是(狭义的)“性能测试”。该测试也决定了系统能否发布。除此之外的其他测试则是为了更有效地运营项目或者其他目的而实施的。

“Rush Test”“压力测试”等不是根据测试目的来定义的,它们表示的只是测试的执行方式,因此在什么时间执行是由测试目的决定的。压力测试根据目的的不同,可以分为“性能测试”“临界测试”“耐久测试”等类型,具体做法都是在短时间内向系统发起大量的访问,以此来测量结果。一般会再现多个同时在线的用户的使用情况。在某些情况下,批处理时大量数据的流入也属于这一类。

下面将对各个种类的测试进行更详细的说明。

性能测试的种类

  • 狭义的性能测试

    这个是最为重要的测试,目的是判断是否能达到要求的性能。

    实施时间 在系统测试阶段实施。前提是系统测试的功能部分已经全部通过测试,确定之后不再需要系统变更,并且已经做好了进行运用管理和批处理操作的准备,包含此动作的性能测试也已经准备好。如果没有满足这些前提条件,那么性能测试完成后,系统性能也有可能会发生变化,所以请尽量在上述前提下执行性能测试。

    测量项目 性能测试需要确认以下3个性能指标是否均已达成。

    1. 吞吐(处理条数 / 秒)
    2. 响应时间(秒)
    3. 同时使用数(用户数)

    此外,确认服务器日志以及压力测试工具的记录,同时确认在测试中是否出现了错误信息。如果出现了错误信息,那么这个处理就有可能在执行过程中被跳过了,也就没有完成充分的性能验证。这种情况下就需要首先消除错误,然后再次执行测试。

    如果已经定义了系统运行时资源使用率的上限(例如,遵守CPU使用率在50%以下等),则还需要一起确认资源使用率。

  • 临界测试(临界性能、回退性能、故障测试)

    前面提到过,性能测试用于判定系统能否发布,而除此之外还存在从其他角度进行判定的压力测试。

    {%}

    图 临界测试的种类

    1. 临界测试(最低性能)

      测试是否达到了性能目标的基准。临界测试作为性能测试实施之前的预实施,不用进行太严密的用户场景定义与资源统计,其目的仅仅在于对能否处理预计的处理条数进行简单的确认。另外,在实际执行性能测试的时候,可能会出现负载对象的性能不足、施加负载的一方性能不足、结构错误等情况,临界测试的另一个目的就是发现这些问题。

      若无需进行大规模的准备工作就能立即执行的话,应该在系统完成集成测试之后或之前执行一下。

      实施时间 在大规模地正式实施性能测试之前,需要与各相关部门进行协调。有时候性能测试的实施时间是有限制的,因此测试负责人或服务器管理者应该事先确认好自己责任范围内的测试是否能正常进行。

      测量项目 不需要花费太多精力,只要进行最小限度的确认就可以了。

    2. 临界测试(最大性能)

      这个测试的目的在于,在负载超过性能目标的情况下,把握系统承受程度的上限,以及当时的情况和瓶颈。

      如果需求定义中没有要求进行临界性能的测量,那就没必要实施这个测试了。不过,在实际向客户报告测试结果的时候,可能会被问到“超过这个负载的时候能正常运行吗”“验证过流量控制和超时功能了吗”等问题。系统发布后,在超负载的情况下,如果流量控制、超时、运维监控的阈值检测机制等不能按照预想的那样正常运行,就会出问题,有时甚至会被当成残次品。为了消除这些隐患,我们要执行临界测试。要想通过验收,性能测试是必不可少的一项工作。而临界测试则非如此,而是项目方为了维护项目成果、避免风险而自发实施的测试。

      实施时间 在系统测试阶段顺利通过性能测试后,如果有足够的时间就进行此项测试。这个时候可以进行两种测试。第一种是偏向基础设施的测试,在施加了与生产环境相似的流量控制的状态下,确认流量控制功能能否正常运行。另一种是在不进行流量控制的状态下,确认系统所能处理的上限以及这个时候的情况和瓶颈原因。在进行了这两个测试后,如果能基于明确的记录,对系统在超负载时的情况进行说明,客户一定能认可这个报告。在某些情况下,如果很好地执行了后面提到的“基础设施性能测试”,也可以不实施这里的第一种测试。

      如果系统是横向扩展结构,那么也需要验证横向扩展结构下达到临界负载时的运行情况。理想情况下,在达到最大负载时,AP服务器和DB服务器的CPU使用率会达到100%,或者网络带宽的使用率会接近100%,像这样施加负载让资源达到上限的话,那么作为临界性能测试的测试结果就可以说足够了。如果资源使用率没有达到100%就已经到了性能界线,吞吐也不能继续提升,或者增加负载也只是导致响应变差,那一定是哪里的设置存在瓶颈,必须搞清楚原因。

      在从长远的角度计算系统使用人数的增加量以及针对这种情况的估算指标时,除了在纸上计算之外,还可以一并参考临界测试中阶段性的负载增加以及资源使用量。特别是与公司内部系统不同,在互联网系统中,可能会出现用户突然增加的情况,因此为了建立估算战略,事先进行测量是非常重要的。

      测量项目 实施临界测试的方式是一直施加负载直到达到最大吞吐。使用压力测试工具增加并发度来生成负载的情况下,并发度增加到什么程度也是一个基准。此外,如前所述,为了判断资源是否用尽,也要一起参考服务器的CPU使用率。

    3. 回退性能测试

      回退性能测试也属于一种故障测试。在那些为了确保可用性而使用了冗余结构的系统中,我们需要验证当其中一部分处于停止状态时,是否能获得预期的性能。如果存在回退情况下的性能需求定义,就要进行这个测试。即使没有进行需求定义,如果在生产环境中运行时发生回退,导致没有获得预期的性能,也会很棘手,所以要尽可能地把这个测试加入到项目的验证计划中。

      {%}

      图 回退性能测试

      实施时间 分为两种情况,一种是在系统测试阶段的性能测试结束后执行,另一种是在后面将会提到的基础设施性能测试的过程中执行。如果冗余结构以及可用性功能在系统基础设施中就完成了,并且能够与搭载的应用程序剥离开来,那么只需在基础设施性能测试中执行回退性能测试就可以了。其他情况下,由于要让应用程序在类似于生产环境的环境中运行来进行测试,因此就要在性能测试之后来执行了。

      不仅要对一部分处于停止状态的结构进行性能测试,也要对运行过程中停止或者再次启动时响应时间的变化进行确认。

      测量项目 通常的检验方法是,作为测量指标,通过吞吐来确认最大性能,以及通过响应时间和是否发生错误来确认行为的变化。

  • 故障测试

    故障测试实际上并不属于性能测试的种类,一般被归类到集成测试或系统测试中执行的故障测试。不过,在发生与性能相关的故障时,需要结合压力测试一起实施,而且故障测试与这里介绍的其他测试手法相近,所以笔者就在这里进行解说了。

    故障测试的目的是触发高负载时会出现的故障,判断那种情况下系统的行为以及错误恢复是否与预计的一样。特别是那些会出现高负载但又追求高可用性的系统,故障测试是必需的。

    实施时间 如果作为基础设施可以分离开来的话,可以在集成测试和系统测试的基础设施上进行故障测试。如果不能分离,则可以在性能测试和临界测试等完成后,基于已经确立的性能测试和临界测试的手法来进行测试。

    需要注意的是,如果在一般的性能测试和临界测试等场景中直接执行的话,有可能不能触发目标故障点,而是在别的地方出现瓶颈,导致不能触发希望出现的性能故障。这个时候,需要重新考虑负载场景、系统结构和设置,直到可以触发希望出现的性能故障。

    测量项目 首先着眼于服务器以及负载终端的错误,确认那个时候的吞吐以及平均响应时间,将其作为参考指标。

  • 基础设施性能测试

    在最近的系统搭建中,大多会将应用程序和基础设施分离开来,分别制定搭建计划,然后在集成测试或系统测试中才将其汇合到一起。基础设施中包含中间件(DB或AP服务器)的情况也很多。此外,基础设施作为基础,有专业负责人或供应商执行别的调度计划和检查,笔者认为,采用和应用程序不同的流程更容易推进。综合基础设施和私有云等一开始往往不能准备好应用程序,所以有时就需要在没有应用程序的情况下进行基础设施的发布及基础设施测试。

    基础设施性能测试的目的与必要性

    基础设施性能测试是与应用程序分离开,从基础设施的观点来进行的性能测试。基础设施性能测试的目的是防止在后面的系统测试阶段中基础设施出现性能问题导致返工或计划变更。基础设施搭建团队通过预先进行负载试验,来尽量规避风险。

    {%}

    图 基础设施性能测试的主要验证项目

    只要没有作为验收条件进行规定,基础设施性能测试就不是必需的。不过,如果在系统测试后的性能测试中才发现基础设施存在性能问题,返工成本就会很大,而且也有可能会影响到计划。为了不出现这样的情况,强烈建议在基础设施方面进行与实际生产环境相似的性能测试。

    实施时间 基础设施搭建结束后,在基础设施的集成测试中故障测试完成之后实施。

    在基础设施上进行性能测试,其最大课题就是在应用程序还没有完成的状态下如何预估出需要的性能,以及怎样使用作为样本运行的应用程序。

    测量项目(样本应用程序) 评价的对象不同,测量的应用程序也不同。

    1. 从网络到Web服务器的基础设施性能测试

      在Web服务器上部署静态资源,然后对其发起大量访问就可以了。

    2. 包含依赖于会话的处理在内的基础设施性能测试

      使用依附于应用程序的样本程序。如果是WebLogic的话,就经常使用PetShop或MedRec等作为样本项目。这些程序会进行包含登录在内的会话管理,因此使用负载均衡器或Web服务器来进行会话和cookie的处理,然后分发,这样作为性能测试来说就足够了。

    3. 使用数据库或缓存网格(Cache Grid)或KVS的情况

      这些服务都不是直接从外部来访问,而大多是从AP服务器来访问的,因此很多时候不需要经过全部的基础设施。这种情况下,建议一个一个地单独验证。各种测试工具应该都已经准备好了。

      在进行数据库的基础设施测试时,为了按照事先想好的处理流程编写脚本,或者预设好实际的运行步骤并添加负载,使用 Oracle Real Application Testing 或者 Oracle Application Testing Suite 的 Load Testing Accelerator for ORACLE Database 也很方便(后述)。

      在基础设施性能测试中,特别是与存储和数据库相关的测试,需要准备好与生产环境相同的数据量来验证。另外,测量备份和恢复所需的时间以及运维批处理能否在一定时间内完成也应该包含在基础设施性能测试中。

    基础设施性能测试的性能目标

    在基础设施性能测试中,除了样本应用程序之外,另一个课题就是应该以什么样的性能目标作为基准。在讨论目标值时,一般按照下面的顺序进行。

    ① 提出性能目标信息

    让应用程序开发部门提出严谨的性能目标信息。具体包括负载均衡器和Web服务器上必需的同时连接数、每秒的请求数、网络流量(bps)等。DB基础设施的情况下,只有简单的处理数和同时访问数是不够的,如果不能在应用程序这里更进一步,让其提示与业务相同级别的SQL的同时执行信息,就不能完成充分的基础设施测试。

    如果没有很好地定义这些指标就进行应用程序设计,就会在开发时忽视性能,因此应该对应用程序开发部门明确地提出要求。

    ② 自己预估

    如果不能获取上述信息,或者对应用程序开发部分预估的信息不够放心,就需要自己来预估,顺便进行验证。

    下表汇总了预估目标信息所需的项目与知识。

    表 计算基础设施性能测试的性能目标

    {%}

    使用表中的各个项目如何计算出各个目标值呢?方法如下所示。

    算式中带圆圈的数字就是表中项目的编号。

    【带宽(bps)的计算方法】

    (每小时的处理页面数)× 每个页面的大小 × 没有命中缓存的概率((① × ② × ④)×(⑤ × ⑥)×(1 -⑦))÷ 3600s(1h)× 8(bit)= 带宽(bps)

    【吞吐(请求/秒)的计算方法】

    (每小时的处理页面数)× 没有命中缓存的概率((① × ② × ④)×(1 -⑦)÷ 3600s(1h))= 页面请求数 / 秒

    【同时访问数(用户人数)的计算方法】

    (每小时的处理页面数 )× 平均思考时间(① × ② × ④)× ③ ÷ 3600s(1h)= 同时访问数

    【同时访问数(活跃连接数)的计算方法】

    ((① × ② × ③ × ④)÷ 3600s(1h))×(⑧或者⑤中比较小的那个值)÷(HTTP KeepAlive 的预计时间或者③中比较大的那个值)

    “同时访问数”实际上会比这里的值更小。这是因为浏览器能够使用一个连接来处理多个内容。如果要进行更精确的计算,就需要考虑每个内容的平均响应与连接的整合度。

  • 应用程序单元性能测试

    应用程序的单元性能测试是在集成测试执行之前进行的测试。在集成之后发生性能问题的时候,如果不能简单地修复,就会导致集成之后的计划延期。为了防止这种事情的发生,应该提前进行应用程序单元性能测试,以防范于未然。

    虽然这个测试并不是必需的,但是为了推进项目顺利进展,防止像前面那样在项目后期才发现问题导致返工,对项目计划和成本产生影响,就需要应用程序单元的开发方在确认性能之后再移交。

    实施时间 在应用程序开发中进行单元测试时,建议同时进行单元性能测试。可以像单元测试一样以测试优先(Test First)的形式组合,在每天进行build时自动测试并检测出错误的机制中加入性能测试。Java的话也可以通过JUnitPerf等来实施。可以在代码中直接要求,若超过了响应时间的目标就报错。

  • 耐久测试

    耐久测试可以归类到故障测试这一大类中。但是,耐久测试可以沿用性能测试的方法,比起单独执行,与性能测试一起执行效率更高。因此,耐久测试作为性能测试的关联领域,多由性能测试的负责人来实施。

    此项测试的目的在于确认系统长时间运作时是否会出现故障或报错、内存泄露、计划外的日志堆积,以及日志轮转(Logrotate)和每日的批处理是否可以正常运作等。建议在追求高可用性的系统中实施此项测试,不过需要确定耐久测试所需的时间。若需要进行1周的连续作业测试,当然就要占用1周的系统,中间若出现失误需要重新实施,或在耐久性测试的结果中发现问题,就需要进行修正并重新测试。因此,在确定耐久测试所需的时间时,至少需要预留耐久测试实施时间的3倍的时间。

    {%}

    图 耐久测试

    实施时间 如果在完成性能测试以及临界测试后,在项目上线前还有时间,并且有充足的时间可以占用系统的话,建议使用这个时间来进行耐久测试。

    测量项目 耐久测试主要关注的是以下项目。

    【响应时间】——需要观察平均响应时间是否有变差的趋势。该指标比CPU等的资源使用率更容易抓住问题。若有逐渐变差的趋势,就代表某个部分有可能发生了劣化

    【内存使用量】——需观察进程中的内存使用量是否在逐步增加,据此可以检测出是否存在内存泄露。但是近年来OS中有缓冲和缓存的机制、堆内存(Heap Memory)和GC的机制,有时会先保证大量的内存,并在其中进行处理,所以需要在理解架构之后进行确认

    【磁盘增加量】——在设计时应该有一个指标,即当访问数量是多少时日志的增加量是多少。然后再回过头来确认实际情况是否和设计时的预想一致,以及其他无关的目录下磁盘使用量是否有增加等

    【其他参考指标】——CPU、线程数、系统内部内存(DB的缓存、Java VM 的堆内部的动态)等

  • 关联领域

    如上所述,性能测试的关联领域有故障测试、耐久测试等。虽然这些测试单独实施起来难度较高,但由于可以利用性能测试的手法,而且大多数情况下都可以由性能测试的负责人来帮忙或者负责,因此在这里对其进行了介绍。要想成功地完成项目,项目组成员就不能持有“只要我负责的那部分没问题就OK了”这样的态度,而是应该所有成员一起努力协作,而项目经理则需要为大家创造更加容易一起协作的环境。

    我们围绕着系统发布前的性能测试进行了解说,但在实际的开发现场,很多时候都是在项目发布后的打补丁以及库文件更新时进行的。为了使系统稳定运行,运维的时候也要能随时在测试环境中增加负载进行测试。

 

{%}

《图解性能优化》从性能的概念讲起,由浅入深,全面介绍了性能分析的基础知识、实际系统的性能分析、性能调优、性能测试、虚拟化环境下的性能分析、云计算环境下的性能分析等内容。