锅炉信息网 > 锅炉知识 > 锅炉学习

当我遇到10亿参数组合

发布时间:

最早提到接口测试的优点时,有一个就是执行效率提升,可能是UI层面执行的N倍。但是今天我要分享的这个案例这个优点的升级版本。某个

最早提到接口测试的优点时,有一个就是执行效率提升,可能是UI层面执行的N倍。但是今天我要分享的这个案例这个优点的升级版本。

某个接口参数倒是不多,但是每个参数的范围略大,最大的将近500个枚举范围,小的也是20个。如果把所有参数组合穷举完,粗略估计可能10亿级别的。

需求就是要把这部分所有参数组合都遍历进行测试,然后我就开始了踩坑了。

初版方案

一开始的想法就是多个循环嵌套,然后并发发起请求,实现起来非常简单方便。如下:

@Log4j2nclass TT extends MonitorRT {nn static void main(String[] args) {n ["types参数集合"].each {n def type = itn ["id类型集合"].each {n def id = itn 2.upto(99) {n def a = itn 2.upto(99) {n def b = itn 2.upto(99) {n def c = itn def params = new JSONObject()n params.id = idn params.endTime = 0n params.type = typen params.paramMap = parse("{"a":"${a}","b":"$b","c":"$c"}")n fun {n getHttpResponse(getHttpGet(url,params))n }n }n }n }n }n }n }n}n

但是方案的缺陷显而易见。

  1. 数量太大,导致后面的异步任务直接被线程池拒绝
  2. 无法控制QPS和并发数

针对这第一个问题,我是增加了异步线程池等待队列的长度,可以我发现了新的问题,就是内存压力太大,这个会在后面的中也遇到。

升级版

针对存在第二个问题,我回归到性能测试框架中,通过动态调整QPS的功能来调整QPS或者并发数,这里我选择了QPS,这个更容易更可控。我的思路是,先把所有参数遍历一遍,存在一个List当中,然后在去遍历这个List,通过动态QPS压测模型把所有请求发出去。

static void main(String[] args) {n def list = []n ["types参数集合"].each {n def type = itn ["id类型集合"].each {n def id = itn 2.upto(99) {n def a = itn 2.upto(99) {n def b = itn 2.upto(99) {n def c = itn def params = new JSONObject()n params.id = idn params.endTime = 0n params.type = typen params.paramMap = parse("{"a":"${a}","b":"$b","c":"$c"}")n }n }n }n }n }n AtomicInteger index = new AtomicInteger()n def test = {n def increment = index.getAndIncrement()n if (increment >= list.size()) FunQpsConcurrent.stop()n else getHttpResponse(getHttpGet(url, list.get(increment)))n }n new FunQpsConcurrent(test,"遍历10亿参数组合").start()n }n

但是新的问题立马就来了,当我运行改代码的时候,发现本机的CPU疯狂飙升,仔细看了一下,原来是GC导致的。存放这么多的数据,内存撑不住了。下面就着手解决内存的问题,这里参考10 亿条日志回放chronicle性能测试中的思路。

终版

这里用到了线程安全的队列java.util.concurrent.LinkedBlockingQueue以及对应长度的等待功能,再配合异步生成请求参数,基本上完美解决需求。这里依旧使用休眠1s来进行缓冲,避免队列长度过大,只有队列长度足够1s的2倍消费即可。

static void main(String[] args) {n def ps = new LinkedBlockingQueue()n fun {n ["types参数集合"].each {n def type = itn ["id类型集合"].each {n def id = itn 2.upto(99) {n def a = itn 2.upto(99) {n def b = itn 2.upto(99) {n def c = itn def params = new JSONObject()n params.id = idn params.endTime = 0n params.type = typen params.paramMap = parse("{"a":"${a}","b":"$b","c":"$c"}")n if (ps.size() > 10_0000) sleep(1.0)n ps.put(params)n }n }n }n }n }n }n AtomicInteger index = new AtomicInteger()n def test = {n def params = ps.poll(100, TimeUnit.MILLISECONDS)n if (params == null) FunQpsConcurrent.stop()n else getHttpResponse(getHttpGet(url, params))n }n new FunQpsConcurrent(test, "遍历10亿参数组合").start()n }n

随着对队列的学习和使用,最近自己也想写一个10亿级别的日志回放功能,到时候对比chronicle看看性能如何,敬请期待。

FunTester原创专题推荐~
  • 接口功能测试专题
  • 性能测试专题
  • Groovy专题
  • Java、Groovy、Go、Python
  • 单测&白盒
  • FunTester社群风采
  • 测试理论鸡汤
  • FunTester视频专题
  • 案例分享:方案、BUG、爬虫
  • UI自动化专题
  • 测试工具专题

-- By FunTester

上一篇:很奇怪我爱你 10

下一篇:火柴-4

精选推荐

  • 催化燃烧设备供应商
    催化燃烧设备供应商

    催化燃烧设备供应商,催化燃烧处理装置厂家,本装置是采用废气先进入喷淋塔过滤——干式过滤—-蜂窝活性碳吸附—脱附再生——催化燃

  • 该不该有模具供应商
    该不该有模具供应商

    今天红姐又来跟我探讨供应商的管理问题了。故事是这样的:供应商来料不良,原因是模具问题。而那个模具是我们找的一家模具供应商做的

  • 什么牌子高压锅好,高压锅哪个牌子好,高压锅什么牌子好,高压锅哪个品牌好
    什么牌子高压锅好,高压锅哪个牌子好,高

    1苏泊尔 双重安全阀门 高压锅双重安全阀,防烫把手,复合底。这款高压锅拥有双重安全阀门,更好的保证使用安全。搭载防烫伤把手,方便起

  • 高压锅啥牌子好,高压锅哪个牌子的好,什么高压锅牌子好,高压锅推荐选购指南
    高压锅啥牌子好,高压锅哪个牌子的好,什

    1、双喜阶梯型复底高压锅推荐理由:高压锅满足上蒸下煮,饭菜同时进行,方便快速,有效提升烹饪效率。多重安全防护,安全系数较高,家人使用

0