专栏文章 性能测试中数据处理经验分享

FunTester · 2023年10月20日 · 2656 次阅读

在性能测试中,有一个无法避免的问题,就是如何处理性能测试用例使用到的数据,其中包括前置数据、运行时数据和后置脏数据清理。

相信大家在做性能测试中也会遇到跟我相同的问题,我分享一下自己的思路和解决方案,仅供参考。仅仅根据个人经验,我将性能测试中数据处理分成以下几种类型。

静态数据

这类数据相信是大家最容易配到的。最常见的就是用户账号、密码,用于进行前置的登录功能。这里就以登录为例,分享一下我遇到的几种情况和解决办法。

一次登录

有些团队会将测试用户的登录凭证有效期设置很长,设置无限长。如果是这种情况的话,通常用一个配置文件将用户登录凭证存下来即可。这也是最简单的,甚至可以将用户的基本配置信息也都存放在一个文件中。使用时,只需将加载文件内容,进行数据初始化即可。

次次登录

这种就比较麻烦,业务逻辑就是用户无操作一段时间以后,用户凭证会自动过期。加入研发也不会为了适配性能测试进行代码改造,那么就需要测试同学解决这个问题。

  1. 通过不间断请求服务,保持用户登录凭证的有消息。
  2. 每次测试前,都将用户登录一遍,然后再进行测试流程。

无论选择哪一种,都会遇到大量用户登录的场景。假如通过并发或者其他技术手段将用户登录这个流程控制在较短的时间内完成,那么第二种是非常不错的选择。若是用户数量太大,登录一遍时间无法减少到可接受范围内。最好选择第一种方式。

动态数据

动态数据分成两类:一种是在测试中产生的;一种是从上下游获取的。这里我们用一般社交软件关注、取关场景分享。

测试中产生

实际测试中,如果选择将两个接口同时测试,Case 逻辑:先关注,再取关。那么就符合这类数据类型。通常我们只需要将两个接口的响应关联起来,假如关注成功之后,再去取消关注即可。最后再日志打点和脏数据处理做点工作即可。

测试中获取

如果实在想单独测试取关接口,那么用例前置条件就是测试用户关注了很多人,足够再测试过程中取关消耗。如果我们选择提前将所有的用户 - 关注列表进行配置化或者保存再数据库中,那么如何再测试过程中管理这些庞大的数据也是个问题,特别是后者又需要进行大量的交互操作。

我一般选择压测前去接口把最新的关注列表信息查到,然后再进行取关操作。然后在压测过程中注意线程安全问题,保障每次取关时参数都是正确的。

异步数据

还有一种数据,虽然也是在动态的,可以在测试中获取也可以在测试中产生,但由于比较特殊,所以单独拎出来说一下。

假如我们想测试抢购业务,有一个业务场景,1w 个用户不断抢购某一些商品(参数商品 ID)。若我们想覆盖商品被抢购一空场景的话,通常会这么设计用例:

  1. 核心进程,请求抢购接口。商品的 ID 或者 ID 列表使用全局变量。
  2. 异步进程,不断更新商品 ID 或者 ID 列表,甚至会调用上架新商品接口。

这个异步进程就是处理异步数据,维护全局变量的有效性。这种 Case 常见于稳定性用例,由于运行时间比较长,对于预制数据包消耗量非常大,需要在测试过程中不断产生新数据,但跟实际被测的接口所需数据不是一对一的关系,而且一对全部的关系。

异步进程还可以监控核心进程中报出的异常。假如是发现某个商品 ID 已经被抢光了,则立即更新全局变量。

分布式

相信都听过分布式压测,本质就是压力源,压力源的数量在整个测试过程中也可能是动态的。以上所有的情况都会更加复杂,单机压测我们要解决的是线程安全问题,而分布式压测场景,就需要再解决分布式安全问题。

我一般使用数据隔离,保障每个节点运行用例时不会相互干扰。这种依赖性能引擎的设计。通过注册中心拿到各个节点的信息,然后在过滤性能测试数据,只使用适合当前节点的。

在其他团队分享到,还有将数据配置文件搞到一个消息队列中,压测时候所有节点都去消耗队列种的消息,通过队列的运行机制实现分布式的数据隔离。目前我看到的大多是流量回放场景用的多,从生产环境抓取流量,清洗之后丢到数据仓库中。压测时再从数据仓库中读取信息,进行回放。

超大配置文件

当我们面对超大量的数据时,比如流量录制文件,单位都是 G。除了使用大数据相关工具以外,我们还可以进行简单的方案,直接提前将文件下载到本地,运行时直接读取流量文件。如果要适配分布式,可以提前将文件分隔,甚至在录制流量的时候直接进行份文件录制。

比如比较流行的 goreplay 框架,它运行的时候直接命令行制定的本地流量文件。如果选择二开可以在运行测试过程中,动态读取流量文件信息。包括在录制流量过程中也是支持条件分隔录制文件的。

对于 Java 的框架来讲,我通常会选择两种方式:

  1. 全量加载。当配置文件不大的情况下,可以直接将文件读取到 JVM 内存中,如果硬件配置足够,流量回放文件也可以一次性读取到内存中。这个需要根据业务场景和硬件配置判断。
  2. 使用本地的队列。当第一种方式无法被接受,可以选择本地的队列。用异步的线程将文件逐行读取丢给队列。测试线程去队列中获取数据,发起请求。根据之前文章中对对 Java 和 Go 常用队列的测试结果,单机进行 10w QPS 级别的性能测试时,队列不会成为瓶颈。

PS:末尾推荐一下 chronicle,基于 Java 的应用程序开发高性能和低延迟的消息队列。根据我的测试,40G 总消息(总文件大小),读取速率 120W TPS。在这个级别的 QPS 测试中,通过网络获取消息内容是非常昂贵的。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册