常见性能测试场景概述
性能测试通常不会覆盖所有业务场景,我们会选取一组具有代表性的场景,通过它来评估整个系统的性能状况,场景的选择将直接影响到性能测试的效果。常见的需要我们重点关注的场景有如下。、
高频发生的场景。
关键的业务场景,例如与交易和支付功能相关的场景。
资源高消耗的场景,包括 CPU、内存、磁盘 I/O、网络带宽等资源。要想进一步判断哪些代码会产生资源消耗,需要从开发工程师那儿了解代码的实现方式。
出现过问题的场景,要定期回归测试这类场景,把性能测试脚本加入持续集成平台定时执行。
除了这些之外,还要根据故事卡的不同实现方式来确定测试场景,重点关注如下性能问题。
慢 SQL:原因比较多,例如用多个条件对一个表做查询,没有将返回数据集少的条件放在前面;SQL 语句中使用字段类型转换、函数操作,没有用到索引;单个事务操作的数据集过大等。
跨表查询慢:需要使用索引,一般来说,单表或两张表的关联查询不会慢,但如果涉及更多表,例如 6~7 个,即使使用索引,仍会出现查询慢的情况。
一般在数据量较小的自测中,这两个问题并不容易暴露。只有当数据达到几十万或者几百万条时,性能问题才能暴露出来。因此多表关联查询时,主表和关联表都要构造足够量的性能测试数据。除了大数据量以外,适当增加一些并发线程也有利于发现系统性能瓶颈,常见的并发相关的性能瓶颈如下。
数据库锁:尽量减少锁的范围,减少锁定资源的数量和时间长度。如果锁使用不合理,可能出现并发访问时的等待,引起性能问题。
数据库连接池:为了提高访问数据库的性能,通常在程序中使用数据库连接池,预先初始化一定数量的数据库连接,并设置允许的最大连接数。当所有连接都处于使用中的状态时,就会出现排队等待释放连接的场景。
数据库锁和连接池引起的性能问题,根本原因都是并发线程抢占资源。测试这些问题需要提高并发线程数量。数据库连接池的性能问题比较好复现,当线程数增大后,常常会有线程处于等待状态,这里需要验证的是被测接口的吞吐量,达不到预期则可判断为性能问题。在检查数据库锁时,有写操作的接口是测试重点,用多线程并发调用接口,持续一段时间,看是否会造成死锁,特别注意那些加锁且操作数据量比较大的 SQL 语句。此外,影响测试场景的选择的因素还有如下几点。
线程池:原理、性能问题和数据库连接池类似,测试方法也相似,主要验证线程池能否满足业务需要的吞吐量。
缓存:测试与缓存相关的性能场景时,要关注测试数据的多样性,可以使用脚本批量生成测试数据,也可以使用脱敏后的产品数据。验证击中缓存和直接从数据库读取(缓存中找不到数据时会直接到数据库查询)的性能。由于缓存占用内存较大,可能会频繁引发虚拟机的内存垃圾回收,导致系统性能下降。测试时可以在缓存中加载大量数据,并长时间访问缓存,监控内存垃圾回收的频率。
第三方服务:第三方服务性能的好与坏通常不受测试人员控制,与第三方服务集成时,测试工作主要集中在自己的代码上。可以 Mock 第三方服务做性能测试,测试之前需要和开发人员讨论,了解业务处理代码中比较耗时的部分,这些场景就是测试重点。若处理第三方数据的代码比较耗时,则需要在 Mock 中构造特定的返回数据做验证。
数据传输速度:在内网部署的应用中,较少出现传输相关性能问题,而当跨机房调用时易出现性能瓶颈。验证过跨两个云迁移数据库的性能场景,在两个云上各自业务的处理速度都较快,但云与云之间的公网传输速度慢,导致并发的迁移线程数无法提升。
代码的逻辑和算法:对测试工程师来说代码的实现通常是一个黑盒,但其中很多代码问题都可能造成性能缺陷。例如对同一个功能,在实现方式上,开发人员可以选择性能好但线程不安全的类,也可以选择线程安全但性能不好的类;程序中可能有不合适的排序算法,或者其循环内有过多不必要的对象。此外代码中线程同步的范围、集合类对象初始大小等设置也会造成性能隐患。为了发现代码导致的性能问题,在测试过程中测试人员需要同时提高线程数和测试数据量,一些代码会因为测试数据量的增加而变慢,例如排序算法的代码。
上面介绍了日常测试中经常碰到的性能测试场景,除此之外也有些场景并不需要压测,例如把同步改为异步处理、使用比较成熟的开源类库、使用在多个项目中做过性能验证的代码框架。此外还有一些数据量小、并发量小的功能可以不做压测。从逻辑上讲,任何一行代码或者配置的改动,都有可能影响性能,当然对经过代码评审确认修改后不影响性能的代码,可以不做压测。
版权声明: 本文为 InfoQ 作者【穿过生命散发芬芳】的原创文章。
原文链接:【http://xie.infoq.cn/article/994c5a80967acc7c7c3ec7495】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论