性能测试--性能测试数据准备

本文涉及的产品
性能测试 PTS,5000VUM额度
简介: 关于如何准备性能测试数据,相信不少性能测试人员也踩过不少坑:比如数据量不足,导致性能表现非常好,忽略了一些潜在性能问题;数据分布不合理,导致测试结果与线上差异较大,又要推到重来。经过n多次被坑之后,总结下经验。我们把测试数据准备分为两类数据:铺底数据和参数化数据。

关于如何准备性能测试数据,相信不少性能测试人员也踩过不少坑:比如数据量不足,导致性能表现非常好,忽略了一些潜在性能问题;数据分布不合理,导致测试结果与线上差异较大,又要推到重来。经过n多次被坑之后,总结下经验。我们把测试数据准备分为两类数据:铺底数据和参数化数据。

什么是铺底数据?一般情况下,产品上线后,数据量是不断增加和累计的过程。刚上线时,数据量较少,数据库查询及更新速度快,服务响应及时性较好。随着数据量的累积,数据量不断增加和膨胀,系统的操作响应时间会随着数据量的不断增加而变得越来越长。所以,在性能测试模拟时,要考虑一定规模数据量情况下的性能是否能满足预期,比如考虑半年或一年的业务量。

什么是参数化数据?在压力测试时,通常模拟不同的用户行为,或者业务行为,从系统所提供的API来看,我们需要参数化用户账号等数据,如考拉海淘产品,压测下单场景时,我们要参数化用户数据,哪些用户进行下单;参数化商品数据,这些用户购买什么产品等。


一、性能测试数据准备


铺底数据准备


铺底数据有目的: 铺底数据的首要目的是让性能测试环境与线上保持一致,或者说接近线上真实情况。一个是保证待测系统有一定的规模,比如半年或一年后的用户规模。另一个是为压测做准备,准备每个要压测的请求需要使用到的数据,这部分数据涉及到具体的业务,对性能测试结果影响比较大,具体说明可参考“参数化数据准备”章节。

根据以上两点,将铺底数据划分为两块:

  1. 只做铺底,在压测中不会访问到的数据,这部分数据是为了使数据库达到一定的规模,以发现数据库查询、更新等性能瓶颈,如忘记建立索引,查询SQL不合理等问题。只为铺底,压测时不会用到的这部分数据,在预设的过程中就比较随意了,不用考虑数据是否合理,也不用考虑业务关联关系,只要符合数据库设计规则,能插入数据库即可。
  2. 另一部分数据是在压测时要用到的数据,比如API要传参过去的数据,或者请求响应数据。这部分数据在铺底的时候就要精细化的设计,包括数据大小,数量,分布等。

铺底数据量多少合适? 这个完全根据产品的规模来预估,比如产品预计半年后注册用户数达到100w,则铺底的时候需要铺底100w用户账号。如果是已上线产品,根据线上数据库数据量进行预估,可以根据用户规模的比列进行铺底,如线上注册用户数一千万,线下铺底注册用户数100w,则总体数据规模为线上的十分之一左右。实际情况下,这里会略微复杂,比如还要考虑线上数据库集群和测试集群的硬件差异等,需做适当的调整。


参数化数据准备


如果我们从系统接口调用角度来看的话,参数化数据包括两类:一类是我们要传参给接口调用的数据,比如用户账号ID,商品ID等。 另一类是接口返回的结果数据,如获取商品详情时,需要返回商品的数量、颜色、描述信息等,这些数据必须是事先准备好的。

在进行参数化数据准备时,对于已经上线的产品,可以统计不同铺底数据的分布规律。从网易宝和之前的timeline的两个产品的数据统计来看,大多数数据的分布接近2/8原则。比如活跃用户数占注册用户数的比例为20%,非活跃或者欠活跃的用户占比为80%左右。针对具体业务,80%的业务是由20%的活跃用户产生,20%的业务是由80%的非活跃用户产生。所以参数化测试账号时,对这20%的用户账号需要进行精心铺底。


测试账号准备


注册用户数是产品用户规模的衡量指标,一般会先铺底一定规模的用户账号。

铺底多少测试账号?根据产品本身的特点、参考竞品的用户量、以及产品的推广计划,预估半年后要推广到100w用户。那这100w是指注册用户数。一般互联网产品活跃用户是注册用户的10%~20%,不同类型的产品略有差异。那么我们在准备数据的时候,会考虑铺底100w用户,其中80%左右的用户是非活跃用户,用户相关数据会比较随意的铺底,保证铺底主表及关联表即可;其中20%左右的用户是活跃用户,是压测时要用到的数据,这20%的用户信息,比如好友关系、发表的微博数量等,都需要设计进行铺底。


读请求数据准备


读请求一般即为GET请求,影响GET请求性能的主要有两部分:

  • 一是GET请求返回的数据量的多少
  • 一是GET请求传入参数的数据量多少

一个常见的读请求定义为:

URI:/video/details?deviceId=123456 
Method:GET
Reurn:{
"message": "success",
"timeline": {
"list": [
{ "from": -23261042219000, "to": -23261042199000 },
{ "from": 1388523600000, "to": 1388523921000}
]},
"code": 200
}

其中,deviceId是接口调用时要传的参数,这里是指设备Id;Reurn是指该接口的返回数据,返回数据内容为该设备的详情信息。那么在铺底数据的时候,我们要铺底deviceID来虚拟出若干设备出来,同时这些设备的详情信息不能为空,也需要进行铺底;这就涉及到接下来要介绍的,读请求返回数据量准备和传入参数deviceId的数据量准备。


读请求返回的数据量准备


读请求返回的数据量大小要与实际情况基本一致,返回数据量不能太大,太大会偏离实际情况,增加数据库压力,网络传输时延等,导致测试结果比实际情况差的多;返回数据量不能太小,比如获取一篇博文,博文不能全部返回空,会比实际情况好,导致遗漏一些性能风险点。如示例中的RETRUN内容为2条信息左右,通常情况下用户的设备详情信息在2~10条左右,这里铺底就要考虑铺底随机2~10条。

返回数据量的多少,取决于预设的数据量,例如测试活动页的性能,预设10个商品和200个商品时,得到的性能测试数据不一样,发现的问题点也可能不一样:10个商品时,性能开销在memcached网络IO上;200个商品时,发现性能开销在返回数据的序列化上。再比如,获取博客详情信息,博客长度为几百字和几千字的性能也是会有差异的,体现在从缓存或者数据库中获取数据量多少时的性能差别等。

方法:预设这部分数据时,需要了解返回数据的上限是多少,即找相关开发了解一个活动页面最多会有多少数据,分别测试常规情况下活动页的性能以及极限情况下活动页的性能。

另外返回数据量的多少可能会使得网络带宽首先成为瓶颈点,当返回的数据量过多时,应该通过分页等策略限制返回数据量的大小。


传入参数的数据量准备


传入参数的数据量是指,GET请求中需要的参数从多少数据量中获取,例如获取博客详情接口,给定的参数可以是一个博客地址,不停的获取该博客的内容,也可以是10w个博客地址,随机的获取这些博客的性能。如示例中的deviceId在压测中会从10w个设备中随机选择进行测试,也就是我们要在测试前铺底10w个设备。

这种情况下,需要找开发确认,代码实现中是否有缓存相关操作,如果热点博客会被缓存住,那一个博客的情况下,测试的是全部被缓存住的性能,10w个博客,根据缓存大小的不同,可能会测试到不同情况下的性能。

对于有热点缓存的情况,建议可以测试下把缓存关掉时的性能,发现极端情况无缓存时,是否存在性能问题。


读请求的传入参数与返回数据量两者结合


有些时候,以上两种情况都需要考虑,即:传入参数的数据量以及返回的数据量,例如获取博客的评论信息接口:基于80/20原则,20%的博客为热点博客,这20%的博客的评论数量较多,另外80%的博客为非热点博客,评论数较少。为了得到更真实的性能结果,我们需要把这多种情况都考虑进去。


写请求数据准备


写请求,一般情况下指POST、PUT等请求,也即是向服务端提交数据的请求类型。一般情况下写请求对服务端造成的压力会大一些,因为涉及到数据更新,如数据库更新、缓存更新等。因此,写请求的数据量,对数据库的压力等都是影响性能的条件。写请求关注几点:

  • 写请求对热点数据的更新
  • 写入数据量大小和分布

一个常见的写请求定义如下:

URI: /public/setAsPublic 
Method:POST
Body:{
"deviceId": "111",
"description": "this is my device",
}
Return:
{
"message": "success",
"result": {
"deviceId": "111",
"onlineNumber":0
},
"code": 200
}

该接口是写请求,目的是设置设备的概要信息。deviceId是设备Id,description描述信息。deviceId是参数化数据,需要提前进行铺底的数据。description是描述信息,是文本信息,设置多少字节?需要根据实际情况预设。


写请求对热点数据的更新


写请求有若干种情况,更新单个数据,批量更新多个数据,多个用户同时更新同一个数据等,针对不同类型的写请求,对资源的更新、竞争会造成不同的压力。热点数据更新,是指对该数据有资源竞争的情况,典型的场景例如电商的秒杀场景,大量用户同时抢购同一件商品;例如社交类的热点微博,大量用户同时评论同一个微博;大量用户同时关注同一个明星账号等。测试对热点数据竞争时的性能问题和数据库锁竞争问题等。

所以在准备这部分数据时,即需要准备批量的数据,测试随机购买、随机评论的性能,也需要准备少量的热点数据,测试对热点数据竞争时的性能。


写入数据量大小和分布

当压测写请求时,是需要提交数据到服务端,然后会写入缓存或者写入数据库的,这部分数据量的大小及分布会对性能结果影响比较多,数据量的大小会影响网络传输时间,会影响数据库更新时间,一般情况下,数据量越大,响应延迟会越高。所以,写请求传参的数据量要尽可能符合实际的用户行为,最好统计线上真实数据,博客的长度一般在多少字以内,微博的长度一般在多少字左右等。


二、性能测试数据准备方法


从线上数据库导入真实数据


从线上数据库或者备库导入数据,最大的优势是数据真实性高,数据分布合理,业务压力点及瓶颈点能和线上保持一致,这样测试出的结果与线上实际情况表现会比较接近。比自己模拟数据要可靠的多。

但是,缺点是用户数据需要进行脱敏,而且也要考虑用户的数据是否能直接拿来用,比如用户的手机号,需要脱敏掉,涉及到短信通知等业务需要进行一定的处理,或者mock掉等。

从线上导入数据库推荐准备过程:

  • 先从基础表导出数据,可以全部导出,也可以部分导出
  • 从基础表的数据出发,导出关联表的数据
  • 数据导出后,对敏感的数据进行处理,即按一定的规则进行更新


根据业务规则构造模拟数据


模拟数据优点:符合自己定义的规则,便于使用,比如测试账号可以自己进行编号,参数化使用时方便。

缺点也比较明显:

  • 模拟数据需要大量的梳理工作,要梳理数据库表,理清哪些是基础表,表与表之间的关联等;
  • 要充分把握产品业务,比如社交类产品,要统计和分析用户的好友关系,每个用户的好友个数分布,每个好友发布的微博梳理分布等,这样测试结果才能趋于线上一致。


使用接口进行预设数据


使用接口进行数据预设,需要先根据产品的业务特征来梳理数据的分布规律。针对产品业务抽取要铺底的数据,对该铺底数据进行特征提取,如某电商产品需要整体性能压测,主要业务包括商品浏览、商品购买、订单查询等业务

  • 首先要铺底测试账号,测试账号有多种特征,是否绑定银行卡,是否绑定支付宝,是否绑定其他支付渠道等;
  • 铺底商品信息,根据不同的地区商品信息略有差异,北京商品数量和分布;杭州商品数据量和分布等;
  • 铺底订单信息,多少用户没有下过单,多少用户有0~10单,多少用户有10~100订单等具体分布情况。

针对以上某一项数据可以抽取A、B、C、D、E共5种特征,比如测试账号,A是绑定银行卡的,B是绑定支付宝支付的,C是绑定网易宝支付,D是同时绑定银行卡和支付宝的账号等5类特征,根据线上数据统计5类特征所占的比例。调用注册账号的接口按照各特征所占比例进行生成数据分布。使用接口预设数据相对比较耗时。


使用存储过程预设数据


除了用应用接口进行数据预设以外,也可以通过存储过程进行数据预设。使用存储过程的时候,需要梳理基础表,以及表和表之间的关联。使得一次存储过程的调用,插入数据库中的数据和进行一次业务操作插入的数据要一致。这一点需要开发配合梳理。有了存储过程,可以自己写程序直接调用存储过程插入数据。

如铺底订单信息,针对部分用户铺底订单,订单状态包括30%已完成支付、50%未支付订单、20%取消订单案例,通过以下方式准备:


a.创建存储过程

CREATE OR REPLACE procedure proc_trade(
    v_trade_id in number,                       --交易id
    v_third_ip in varchar2,                    --第三方ip
    v_third_time in date ,                     --第三方完成时间
    v_trade_state in number ,                  --订单状态,0未支付;1已支付;2取消
    o_result out number,                       --返回值
    o_detail out varchar2                      --详细描述
)as-- 定义变量
  v_error varchar2(500);
begin
    --对变量赋值
    o_result:=0;
    o_detail:='验证失败';
  --业务逻辑处理  if v_tradeid >100 then
      insert into orders(id, third_ip, third_time, trade_state, result, detail) 
        values(v_trade_id, v_third_ip, v_third_time, v_trade_state, o_result, o_detail);
      commit;
  elsif v_tradeid < 100 and v_tradeid > 50 then
      insert into orders(id, third_ip, third_time, trade_state, result, detail) 
        values(v_trade_id, v_third_ip, v_third_time, v_trade_state, o_result, o_detail);
      commit;  else
      goto log;
  end if;
--跳转标志符,名称自己指定
<<log>>
        o_result:=1;
--捕获异常
exception
    when no_data_found
    then
        result := 2;
    when dup_val_on_index
    then
        result := 3;
    when others
    then
        result := -1;
end proc_trade;


b.Java调用存储过程

//获取连接connConnection conn = datasource.getconnection();//创建并初始化CallableStatementCallableStatement cs = null;
cs = conn.prepareCall("{call proc_trade(?,?,?,?)}");//设置参数trace_id,third_ip,third_time,trade_state,这些值预先设置好//并且trade_state符合分布比例:30%已完成支付、50%未支付订单、20%取消订单
  cs.setString(1, traceid); 
  cs.setString(2, third_ip);
  cs.setString(3, third_time);
  cs.setString(4, trade_state);  //获取返回值,o_result
  cs.registerOutParameter(5, Types.BIGINT); //执行存储过程   cs.executeUpdate(); //获取返回值


相关实践学习
通过性能测试PTS对云服务器ECS进行规格选择与性能压测
本文为您介绍如何利用性能测试PTS对云服务器ECS进行规格选择与性能压测。
目录
相关文章
|
2月前
|
测试技术 数据库 UED
Python 性能测试进阶之路:JMeter 与 Locust 的强强联合,解锁性能极限
【9月更文挑战第9天】在数字化时代,确保软件系统在高并发场景下的稳定性至关重要。Python 为此提供了丰富的性能测试工具,如 JMeter 和 Locust。JMeter 可模拟复杂请求场景,而 Locust 则能更灵活地模拟真实用户行为。结合两者优势,可全面评估系统性能并优化瓶颈。例如,在电商网站促销期间,通过 JMeter 模拟大量登录请求并用 Locust 模拟用户浏览和购物行为,可有效识别并解决性能问题,从而提升系统稳定性和用户体验。这种组合为性能测试开辟了新道路,助力应对复杂挑战。
111 2
|
8天前
|
数据采集 缓存 测试技术
性能测试中,除了迭代次数,还有哪些因素会影响测试结果?
性能测试中,除了迭代次数,还有哪些因素会影响测试结果?
16 2
|
8天前
|
测试技术 数据库连接 数据库
测试脚本的编写和维护对性能测试结果有何影响?
测试脚本的编写和维护对性能测试结果有着至关重要的影响,
16 1
|
12天前
|
缓存 监控 测试技术
全网最全压测指南!教你如何测试和优化系统极限性能
大家好,我是小米。本文将介绍如何在实际项目中进行性能压测和优化,包括单台服务器和集群压测、使用JMeter、监控CPU和内存使用率、优化Tomcat和数据库配置等方面的内容,帮助你在高并发场景下提升系统性能。希望这些实战经验能助你一臂之力!
28 3
|
23天前
|
缓存 监控 数据挖掘
C# 一分钟浅谈:性能测试与压力测试
【10月更文挑战第20天】本文介绍了性能测试和压力测试的基础概念、目的、方法及常见问题与解决策略。性能测试关注系统在正常条件下的响应时间和资源利用率,而压力测试则在超出正常条件的情况下测试系统的极限和潜在瓶颈。文章通过具体的C#代码示例,详细探讨了忽视预热阶段、不合理测试数据和缺乏详细监控等常见问题及其解决方案,并提供了如何避免这些问题的建议。
48 7
|
1月前
|
机器学习/深度学习 监控 计算机视觉
目标检测实战(八): 使用YOLOv7完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
本文介绍了如何使用YOLOv7进行目标检测,包括环境搭建、数据集准备、模型训练、验证、测试以及常见错误的解决方法。YOLOv7以其高效性能和准确率在目标检测领域受到关注,适用于自动驾驶、安防监控等场景。文中提供了源码和论文链接,以及详细的步骤说明,适合深度学习实践者参考。
333 0
目标检测实战(八): 使用YOLOv7完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
|
1月前
|
机器学习/深度学习 并行计算 数据可视化
目标分类笔记(二): 利用PaddleClas的框架来完成多标签分类任务(从数据准备到训练测试部署的完整流程)
这篇文章介绍了如何使用PaddleClas框架完成多标签分类任务,包括数据准备、环境搭建、模型训练、预测、评估等完整流程。
95 0
目标分类笔记(二): 利用PaddleClas的框架来完成多标签分类任务(从数据准备到训练测试部署的完整流程)
|
1月前
|
机器学习/深度学习 数据采集 算法
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
这篇博客文章介绍了如何使用包含多个网络和多种训练策略的框架来完成多目标分类任务,涵盖了从数据准备到训练、测试和部署的完整流程,并提供了相关代码和配置文件。
51 0
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
|
1月前
|
机器学习/深度学习 XML 并行计算
目标检测实战(七): 使用YOLOX完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
这篇文章介绍了如何使用YOLOX完成图像目标检测任务的完整流程,包括数据准备、模型训练、验证和测试。
167 0
目标检测实战(七): 使用YOLOX完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
|
2月前
|
缓存 Java 测试技术
谷粒商城笔记+踩坑(11)——性能压测和调优,JMeter压力测试+jvisualvm监控性能+资源动静分离+修改堆内存
使用JMeter对项目各个接口进行压力测试,并对前端进行动静分离优化,优化三级分类查询接口的性能
谷粒商城笔记+踩坑(11)——性能压测和调优,JMeter压力测试+jvisualvm监控性能+资源动静分离+修改堆内存