前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >当我遇到10亿参数组合

当我遇到10亿参数组合

作者头像
FunTester
发布2022-12-09 14:20:51
2400
发布2022-12-09 14:20:51
举报
文章被收录于专栏:FunTesterFunTester

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

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

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

初版方案

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

代码语言:javascript
复制
@Log4j2
class TT extends MonitorRT {

    static void main(String[] args) {
        ["types参数集合"].each {
            def type = it
            ["id类型集合"].each {
                def id = it
                2.upto(99) {
                    def a = it
                    2.upto(99) {
                        def b = it
                        2.upto(99) {
                            def c = it
                            def params = new JSONObject()
                            params.id = id
                            params.endTime = 0
                            params.type = type
                            params.paramMap = parse("{\"a\":\"${a}\",\"b\":\"$b\",\"c\":\"$c\"}")
                            fun {
                                getHttpResponse(getHttpGet(url,params))
                            }
                        }
                    }
                }
            }
        }
    }
}

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

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

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

升级版

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

代码语言:javascript
复制

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

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

终版

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

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

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-10-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FunTester 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 初版方案
    • 升级版
      • 终版
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档