性能场景数据必须如此设计,才能让你的系统跑得更快!
2023-04-21 10:05:06
在性能项目中,性能数据是一种重要的输入资源。然而,有些人用很少的数据来做更大的压力,这显然不符合真实的场景。虽然结果很好,但毫无价值。
性能场景中的数据应该是什么?在RESAR性能工程中,应满足场景中使用的数据:
- 模拟符合真实环境的数据分布的IO操作
- 符合真实用户输入的数据,在真实环境中真实模拟用户操作
分别对应:铺底数据和参数化数据。
1 铺底数据在线系统架构中,系统中常用的数据分为:
- 静态数据(红点)
- 动态数据(绿点)
这也是存储在性能场景中的基础数据:
如果没有基础数据,它相当于一个空系统。但在生产环境中,该系统肯定不是空的,所以应该有足够的数据。如果数据不真实,则无法模拟应用程序内存占用、数据库IO能力、网络吞吐量等生产中有真实数据的场景。
静态数据,容易出现的问题是:
- 一想到占网络带宽大,就觉得要用CDN
- 或者觉得不模拟静态数据,不符合真实场景,不支持我们的优化结果
其实数据放在哪里,如何合理,如何低成本,都要综合考虑,而不是随大流:
- 一些官方门户网站没有流量。在技术规划中,CDN必须放置几张图片,以显示更先进的架构
- 一些企业认为网站上的图片非常重要。他们不懂技术,寻找安全感。他们必须把所有的图片都放在自己的服务器上。原来,图片很大,一张有3张~4M,用户一访问,自然会慢慢
这两种极端都是不可取的。外行指示专家工作,基本上没有好的结果,因为有些外行认为只要压力启动,细节就不在乎结果。处理这些问题最合理的方法是:
- 首先分析业务逻辑
- 再次判断实现技术架构
通常有两个地方可以存放:
- Web层的服务端
- CDN
大系统流量大,网络带宽多。在这种情况下,CDN必须放置数据。如果不使用 CDN 技术、数据需要从中央服务器传输到用户的设备,这将导致:
- 高延迟:由于数据需要从远程服务器传输,访问延迟会增加,用户体验会减少。
- 网络拥塞:如果所有用户都从同一个服务器上要求数据,就会导致网络拥塞,降低整个系统的响应能力。
- 安全问题:如果所有用户都从同一个服务器上要求数据,这意味着所有用户的数据都存储在同一个地方。一旦服务器被attack或数据泄露,用户的数据就会受到威胁。
因此,使用 CDN 该技术可以将数据存储在更接近用户的服务器上,提高访问速度和响应能力,减少延迟和网络拥塞,提高系统安全性。
对于一些小型业务系统,由于用户少,整体网络流量要求少,静态数据可以直接放置在负载平衡服务器(如Nginx)或应用服务器中。用户访问一次后,后续访问直接进行本地缓存,不会对系统压力产生太大影响。
1.2 动态数据需要分析,因为CDN可以放置一些动态数据。
- 这些动态数据存储在DB中,没有任何预热加载
- 当使用预热加载时,这些数据将转换为缓存(也取决于架构设计和代码实现),并将其转换为:
按照这个逻辑,我们应该模拟真实场景中业务操作的实际数据量,否则会出现一些问题。当模拟数据量与实际数据量大不相同时,DB、Cache等。
1.3 影响① DB压力的差异在线系统中设置100万用户,在压力测试过程中,由于没有生产数据,数据制作麻烦,直接使用1000个甚至更少的用户来制作性能场景。
一个表中有100万个数据和1000个数据有什么区别?前提条件:硬件环境、数据库、表结构、索引相同,但两个表的数据不同。两个SQL:
1select * from ob_tuning.temp1_1000 where id = '3959805';2select * from ob_tuning.temp2_100w where id = '3959805';
由于表数据量不同:
手表操作细节。第一个手表(用户1000):
第二个表(用户量100w):
只需对比“executing“线路可以看到明显的差距,它告诉我们,当执行句子时,由于数据量的增加,CPU时间显著增加。因此,如果在性能场景中没有足够的基础数据,它在一开始就注定是悲剧。
② 缓存的区别缓存中数据量存在明显差异:
场景中使用的数据越多,缓存必须但要求越大。
③ 使用压力工具的区别压力工具中使用的数据不仅影响压力工具本身所需的内存,还影响性能场景的执行结果。
④ 网络的区别不同的数据量,无论是缓存还是数据库,都与客户端和服务器之间的网络消耗相似。只要客户没有缓存,你就必须去服务器。
因此,我们认为数据量是多是少对客户端和服务器之间的网络压力没有区别。如果你使用CDN,你可以再考虑一下。
⑤ 应用的区别如果数据没有直接缓存在应用程序中,我们也认为应用程序没有区别。无论如何,无论什么样的请求,我们都需要从缓存或数据库中获取数据。Self应用程序 Time没有区别,方法还需要执行。但是,如果您的应用程序直接将数据存储在应用程序的缓存中,则存在差异。同样,数据量越大,对内存的要求就越大。
基于这几点,我们可以看到两个更重要的环节:数据库和缓存,这是直接影响。
例如,如果数据在数据库中执行缓慢,则需要更多的应用程序线程来处理同步调用应用程序。
假设有一个100 TPS系统首先忽略其他时间,只看数据库时间。如果数据库执行需要10ms,应用程序只需要一个线程即可完成。如果数据库需要100ms,我们仍然想达到100TPS,应用程序必须同时处理10个线程。
由于数据量的影响,整个链路上的所有线程、队列、加班等都会发生很大的变化。
要模拟生产时的样子,铺底数据不能含糊不清。
2 参数化数据场景中应该使用多少数据是性能场景中最容易出现问题的环节。
参数化数据的数量取决于场景运行多长时间。场景运行中通常使用两种数据:
- 唯一性数据
- 可重复使用的数据
使用多少参数化数据很容易计算。例如,在一个运行半小时的场景中,如果TPS是100,则需要18万数据:
$数据量 = 30min \times 60s \times 100TPS = 18w$
② 可重复使用的数据量分析如何在真实的业务场景中重复,如电子商务系统中的商品数据量,可以在参数中重复。毕竟,许多人可以同时购买相同的商品。我们假设平均有1000个用户在10种商品中,当我们有18万用户时,我们需要1800种商品:
$商品数量 = 18w用户 \p 1000用户 \times 10 商品 = 1800 商品$
如果参数化数据量过大,压力工具处理不了怎么办?如果JMeter处理文件参数化数据时,参数化文件过长,JMeter会消耗更多的时间。如果这种参数化数据量要求较高,可以通过连接远程缓存(如Redis)或数据库(如MySQL)进行参数化。
2.2 连接Redis做参数化方法1:直接在Jmeter中写Beanshell连接Redis取数据
1import redis.clients.jedis.Jedis;2 //连接本地 Redis 服务3Jedis jedis = new Jedis(172.16.106.130)30379);4log.info(”服务正在运行: "+jedis.ping());5String key = vars.get("username");六String value = vars.get("token");7vars.put("tokenredis",jedis.get(key));
方法二:使用Rediss Data Set组件
两者都可以使用Redis作为参数数化数据源。
2.3 连接MySQL进行参数化① 创建JDBC Connection Configuration。配置用户名密码等连接信息:
② 创建JDBC Request用JDBC Request取回数据:
③ 用${user_name}引用参数完成以上三个步骤,实现DB的参数化。
3 怎么造数据- 用户数据
- 地址数据
- 商品数据
- 订单数据
如何设置数据量?
根据第四个性能计划,如果登录TPS为每秒150,如果根据容量场景的需要,场景在20分钟内(这是一个经验值,在特定场景执行中会发生变化)将增加到最大值,然后执行10分钟,即总时间约为30分钟。
但由于场景在增加,我们一开始并没有要求达到150TPS,我们无法预测TPS的最大值。根据经验,即使在当前的硬件环境中,即使没有缓存,达到300或400也不应该是一个大问题。
如果按最大400TPS计算,运行半小时需要54万个数据,我们创建的用户数量远远大于这个数量级。在这里,我们将首先创建200万由于地址的数据量必须大于用户的数据量,用户数量将超过200万。
首先检查当前DB中的数据量,然后确定要制造多少。
数据量级显然不够。
如何创建这么多数据?制作的数据主要分为:用户数据和订单数据。
- 登录用户
首先了解表结构,只有符合业务逻辑才能创建数据。查看用户表结构和数据:
地址表:
制作数据时,除非你知道表之间的关系,并且存储过程写得6,否则不要直接将数据插入DB。否则,您将使DB混乱,最终必须在数据库的表中更改数据。建议使用接口直接调用来制作数据,操作简单,更安全。
对于代码制作数据,有必要进行以下分析。
用户表与地址表有对应关系,可以通过以下代码查看。地址表中的MemberID是用户ID
1@Override2public int add(UmsMemberReceiveAddress address) {3 UmsMember currentMember = memberService.getCurrentMember();4 address.setMemberId(currentMember.getId());5 return addressMapper.insert(address);6}
构建用户数据就是实现注册流程。
首先分析用户注册代码,直接使用注册代码部分。具体调用代码:
制作数据需要注意注册过程吗?如果我们调整接口来制作数据,我们就不需要它;但是,如果编写代码来打开多线程数据,我们必须了解接口之间的调用关系。
截取中间部分,分析其调用关系:
注册用户表中的密码都是加密的,类代码可以通过注册用户实现:
1@Override2public void register(String username, String password, String telephone, String authCode) {3...4 //获得默认会员级别,设置5 UmsMemberLevelExample levelExample = new UmsMemberLevelExample();6 levelExample.createCriteria().andDefaultStatusEqualTo(1) ;7 List<UmsMemberLevel> memberLevelList = memberLevelMapper.selectByExample(levelExample);8 if (!CollectionUtils.isEmpty(memberLevelList)) {9 umsMember.setMemberLevelId(memberLevelList.get(0).getId());10 }11 //插入用户12 memberMapper.insert(umsMember);13 umsMember.setPassword(null);14}
您可以直接编写代码来构建用户数据:“构建用户代码.java》
只有有了用户数据、用户地址等详细信息,才能完成订单。
- 用户地址
根据用户地址的资源路径找到Controller层,查看用户地址的代码调用关系,如下:
然后找到用户地址的关键代码:
1@Override2public int add(UmsMemberReceiveAddress address) {3 UmsMember currentMember = memberService.getCurrentMember();4 address.setMemberId(currentMember.getId());5 //插入地址6 return addressMapper.insert(address);7}
我们可以从这个代码中观察到这些信息:
- 调用地址接口需要用户登录状态,通过登录状态分析用户ID号;
- 用户ID号是地址代码中的MemberID号;
- 用户ID号是自增加的。
具体参见请参见《用户地址代码制造》.java》。
基础数据可以通过上述代码快速完成,然后打开Java线程池。用户地址数据的时间记录:
最后造出:
在制作基准场景时,将补充表中的订单数据。当这些数据都有时,我们在容量场景中有足够的基础数据。
4 总结性能场景中的数据应该是什么样子的。
制造数据的方法有很多,只要能快速制造足够的数据量,就不必局限于某种制造数据的方法。
在RESAR性能工程中,性能场景需要两种数据:铺底数据和参数数据。应满足铺底数据:
- 一定要产生符合生产量级的数据量;
- 数据量应真实模拟生产的数据分布;
- 真实可用的数据。
参数化数据需要满足这两个条件:
- 足够的参数化数据量;
- 符合真实用户的输入数据。
有了这些知识,数据就不会混乱了。
5 FAQ- 为什么要制造符合生产量级的数据量?
- 为什么在参数化时使用符合真实用户的输入数据?
通常我们在执行性能脚本时不会执行一次,如果按下以上30min 100TPS场景,对于不可重复使用的数据,如果我们在每次执行前制作一次数据,就不容易使用,但不制作数据是不够的。如何解决这些数据问题?做数据库备份和回滚。
静态铺地数据是指图片和视频吗?是的。
参数数据是否影响压力测量机的性能取决于压力测量机的压力?是的。但是,只有分析参数数据量的具体影响才能判断。
如果压力测量环境与生产环境的硬件配置不平等,数据量是否等于缩放?它也应该缩放,但不一定等于。只有通过基准测试才能知道。
参数化直接从DB取出,连接DB。查询数据需要时间,占用数据库资源。这种参数化方法显然对压力测试的性能有影响。为什么推荐这种方法?
当参数数据较多时,建议直接从缓存或数据库中获取数据。但是,您可以独立构建一个缓存或数据库,以存储参数数据,而无需被测系统的缓存或数据库。
jemeter参数文件一般超过多少条数据量会使jmeter成为瓶颈?没有最终结论。还是要看参数化是什么。
创建生产水平,确保应用程序、数据库和缓存在生产压力下运行;参数用户输入数据,确保数据多样性,数据容易导致严重的数据同化,热点集中,无法再现真实性。400TPS运行半小时,数据量应该是72万吗?
若数据是每个用户使用的唯一数据,则应为72万数据。
“很容易计算出我们需要使用多少参数数据(如用户数据)。例如,一个运行半小时的场景,TPS 如果是 100 如果是,那就需要了 18 模拟每一个压测请求都是由不同的用户发起的,这里需要构建18万个不同的用户。
铺底数据是现有数据,参数化数据是压力测试发起请求时产生的新数据?
有两种参数数据。一种是用户输入的,但数据不在铺底数据中;另一种是铺底数据中必不可少的数据,如用户名。
在真实的环境中下订单需要真正的支付。如何解决这个问题?
若对方提供测试系统即可连接。若不提供,则只能mock
尽量模拟真实的用户效果,但我们通常忽略css、js等直接测试主接口的测试web,这合理吗?
后端压力合理。从用户的角度来看,显然是不合理的。 因此,应进行相应的转换。