重放浏览器单个请求性能测试实践

Posted FunTester

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了重放浏览器单个请求性能测试实践相关的知识,希望对你有一定的参考价值。

在最近的工作中,挫败感极大,我做了深刻反思,得出来一个道理:如是观照,实事求是。

原因比较复杂,其中一项是因为某一批接口测试需求比较紧,我之前一直的思路就是尽可能模拟真实数据,使用多用户进行性能测试,一般测试前都需要尽量大量的数据准备工作。但是这次不灵了,接口之间的参数依赖过于复杂,如果真写起来,可真就是把端上的工作重新做一遍,不值当的。

所以我取了个巧,在模拟用户造数据的时候,我直接复制了浏览器里面的接口请求,然后通过不断的刷这个接口去造数据,就不用去一个参数一个参数的写请求了。顺便还能给端上同学写一个简单的性能测试工具Demo,方便他们做一些简单的性能测试。

首先我去解析GETPOST请求,然后通过工具类FunRequest生成一个HttpRequestBase,然后验证一下请求,就可以正常进行性能测试阶段了。

复制请求

这里我采用了复制curl的格式的方式,因为其他的方式数据量太大了,比较复杂,解析起来困难,容易出BUG

复制浏览器请求

GET请求

分享一下复制的结果,删除了域名。

curl 'https://j****.cn/home/course_list?_=1611648498164&custom_directory_id=4630377&origin=0&page=1&page_size=10' \
  -H 'Connection: keep-alive' \
  -H 'sec-ch-ua: "Chromium";v="88", "Google Chrome";v="88", ";Not A Brand";v="99"' \
  -H 'DNT: 1' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/88.0.4324.96 Safari/537.36' \
  -H 'requestid: 010427916771' \
  -H 'Accept: application/json, text/javascript, */*; q=0.01' \
  -H 'X-Requested-With: XMLHttpRequest' \
  -H 'is_new_okay: 1' \
  -H 'Sec-Fetch-Site: same-origin' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Referer: https://jiaoshi-dev.xk12.cn/' \
  -H 'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8' \
  -H 'Cookie: db_log=1; org_id=640; user_action_cookie=user_action_87cf9c4d-1e22-4c8c-982e-a4419fa6dc1b_62951571858; teacher_id=9fec845f498a47abb68426c14f90693e' \
  --compressed

POST请求

分享一下复制的结果,删除了域名,too!

curl 'https://j****.cn/myResourcePool/deleteResource' \
  -H 'Connection: keep-alive' \
  -H 'sec-ch-ua: "Chromium";v="88", "Google Chrome";v="88", ";Not A Brand";v="99"' \
  -H 'DNT: 1' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36' \
  -H 'requestid: 011342477158' \
  -H 'Accept: application/json, text/javascript, */*; q=0.01' \
  -H 'X-Requested-With: XMLHttpRequest' \
  -H 'is_new_okay: 1' \
  -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' \
  -H 'Origin: https://jiaoshi-dev.xk12.cn' \
  -H 'Sec-Fetch-Site: same-origin' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Referer: https://jiaoshi-dev.xk12.cn/myResourcePool_vm/my_resources' \
  -H 'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8' \
  -H 'Cookie: db_log=1; org_id=640; user_action_cookie=user_action_87cf9c4d-1e22-4c8c-982e-a4419fa6dc1b_62951571858; teacher_id=9fec845f498a47abb68426c14f90693e' \
  --data-raw 'res_id=2317045&res_type=3' \
  --compressed

生成HttpRequestBase对象

这里我是把复制的请求写到本地的一个文本文件中,首先读取,然后遍历处理。

    public static HttpRequestBase getRequest(String path) {
        def fileinfo = WriteRead.readTxtFileByLine(LONG_Path + path).stream().map {it.trim()}
        def base = new CurlRequestBase()
        fileinfo.each {
            if (it.startsWith("curl")) {
                def split = it.split(" "2)
                def type = split[0]
                def value = split[1]
                base.url = value.substring(value.indexOf('h'), value.lastIndexOf("'"))
            } else if (it.startsWith("-H")) {
                def split = it.split(" "2)[1].split(": ")
                base.headers << getHeader(split[0].substring(1), split[1].substring(0, split[1].lastIndexOf("'")))
            } else if (it.startsWith("--data-raw")) {
                base.params = getJson(it.substring(it.indexOf("'") + 1, it.lastIndexOf("'")).split("&"))
                base.type = RequestType.POST
            }
        }
        base.type == RequestType.GET ? FunRequest.isGet().setUri(base.url).addHeader(base.headers).getRequest() : FunRequest.isPost().setUri(base.url).addHeader(base.headers).addParams(base.params).getRequest()
    }

中间用到了一个CurlRequestBase内部静态类。

static class CurlRequestBase {

        String url

        RequestType type =RequestType.GET

        List<Header> headers = new ArrayList<>()

        JSONObject params = new JSONObject()


    }

性能测试

这个比较容易,接入之前的性能测试框架即可。

public static void main(String[] args) {
        def request = getRequest("get")
        output FanLibrary.getHttpResponse(request)

        def thread = new RequestThreadTimes<HttpRequestBase>(request, 100)
        new Concurrent(thread,30,"FunTester get请求测试").start()

        testOver()
    }

控制台输出

响应的数据量有点大,这里就不放响应结果了,直接放性能测试结果。

INFO-> gc回收线程开始了!
INFO-> 线程:FunTester get请求测试16,执行次数:100,错误次数: 0,总耗时:12.92 s
······省略········
INFO-> 线程:FunTester get请求测试19,执行次数:100,错误次数: 0,总耗时:14.017 s
INFO-> 总计30个线程,共用时:14.033 s,执行总数:3000,错误数:0,失败数:0
INFO-> 数据保存成功!文件名:/Users/fv/Documents/workspace/fun/long/data/FunTester get请求测试2021012617384730
INFO-> 
~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~ JSON ~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~
>  {
>  ① . "rt":132,
>  ① . "total":3000,
>  ① . "qps":225.86109542631283,
>  ① . "failRate":0.0,
>  ① . "threads":30,
>  ① . "startTime":"2021-01-26 17:38:47",
>  ① . "endTime":"2021-01-26 17:39:01",
>  ① . "errorRate":0.0,
>  ① . "executeTotal":3000,
>  ① . "mark":"FunTester get请求测试20210126173847",
>  ① . "table":"\r\n\t\t\t\tFunTester get请求测试30·····省略,见下图····\r\n"
>  }
~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~ JSON ~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~
INFO-> 
    FunTester get请求测试30

 >>响应时间分布图,横轴排序分成桶的序号,纵轴每个桶的中位数<<
  --<中位数数据最小值为:93 ms,最大值:204 ms>--
                                                                  ██ 
                                                                  ██ 
                                                                  ██ 
                                                               ▅▅ ██ 
                                                            ▃▃ ██ ██ 
                                                         ▃▃ ██ ██ ██ 
                                                   ▂▂ ▇▇ ██ ██ ██ ██ 
                                          ▁▁ ▄▄ ▇▇ ██ ██ ██ ██ ██ ██ 
                                 ▂▂ ▅▅ ▇▇ ██ ██ ██ ██ ██ ██ ██ ██ ██ 
                     ▁▁ ▄▄ ▅▅ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ 
            ▃▃ ▅▅ ▇▇ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ 
   ▂▂ ▅▅ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ 
▃▃ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ 
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ 
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ 
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ 
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ 
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ 
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ 
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ 
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ 
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ 
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ 

INFO-> gc回收线程结束了!

Process finished with exit code 0

最后的响应结果需要使用等宽字体查看才行,如果系统默认的字是非等宽的,请参照下图:

FunTester性能测试结果

关于如何使用性能测试框架和生成性能测试结果,有兴趣的可以翻一翻以前的文章。


FunTester,非著名测试开发,文章记录学习和感悟,欢迎关注,交流成长。
  • Gitee地址 https://gitee.com/fanapi/tester
  • GitHub地址 https://github.com/JunManYuanLong/FunTester

点击阅读原文,查看公众号历史文章


以上是关于重放浏览器单个请求性能测试实践的主要内容,如果未能解决你的问题,请参考以下文章

重放浏览器多个请求性能测试实践

开放API网关实践之重放攻击及防御

api-gateway实践(19)HTTP请求防篡改

性能测试分析之HTTP资源消耗探究

后端工程师压力测试并发测试实践

性能测试中标记请求参数实践