你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

性能测试 性能测试实战(一)如何分析一个web端 http请求接口的请求和响应耗时过程?http请求响应耗时时长可能与哪些因素有关? 简易分析篇

2021/12/26 6:47:17

文章目录

前言

性能测试 考虑点 时间特性

性能测试 性能指标 响应时间

性能测试 页面请求加载过程 示例讲解

1、Chrome浏览器请求 百度首页 示例

2、百度首页 请求耗时分析

性能测试 页面请求加载过程 实战讲解

Java SpringBoot框架 示例

1、GET请求 响应耗时 请求不带参数

    1.1    浏览器访问接口 请求捕获响应时间和响应内容

    1.2    浏览器查看接口 请求方法​​

     1.3    SpringBoot  源码示例

    1.4    响应耗时 分析

2、GET请求 响应耗时 带参数

   2.1    浏览器访问接口 请求捕获响应时间和响应内容

    2.2   SpringBoot  源码示例

    2.3    响应耗时 分析

    2.4    Mysql请求耗时 过程分析

3、 POST请求 响应耗时 带参数、数据校验、第三方接口查询

    3.1    浏览器访问接口 请求捕获响应时间和响应内容

    3.2   SpringBoot  源码示例

    3.3    响应耗时 分析

4、响应请求耗时 拓展示例

结束语


前言

        如何分析一个web端 http请求接口的请求和响应过程?

        http请求响应耗时时长可能与哪些因素有关? 

 发起请求到请求完成的响应时间示例图解.png


性能测试 考虑点 时间特性

时间特性

主要指的是软件产品的事物响应时间(用户发出请求到收到应答的这段时间)


性能测试 性能指标 响应时间

响应时间

        响应时间是最能反应服务器性能的指标之一,也是用户最关心的业务体验。比如登录某个商城网站时,只消耗1s钟。在进行性能测试时,是通过对事务响应时间(Transaction Response Time)来分析服务器的响应速度。


性能测试 页面请求加载过程 示例讲解

1、Chrome浏览器请求 百度首页 示例

1、Time 响应请求耗时

        即一个网站请求时所需要加载的url队列,记录每个资源各自单独完成请求的响应耗时

2、204ms 百度主页html响应实际耗时

       204ms即204毫秒,1秒=1000毫秒,html响应时间为0.2秒左右。

3、53 requests 请求url队列

        从该列可看name列对应查看响应内容为返回耗时,当然一个网站的常规组成有 静态资源:html、js、css、媒体资源(图、音频、视频),动态资源:数据等。即打开百度网站首页需要加载53个不同的url请求。

4、2.1 MB resource

        页面打开所需资源空间大小,即百度首页整个业务所包含的静态和动态资源的总和

5、Finish: 747ms

        页面加载完成耗时时间,即百度首页正常页面全部加载完毕所需耗时,这个与“肉眼”看到的可能有轻微误差,部分资源可能是后台请求实际前端页面可能再此之前已经展示完毕。

2、百度首页 请求耗时分析

         按响应时间倒序排列,可看出网站打开到加载完成不同耗时的具体时间。常规情况下静态资源文件越小时间耗时越少,不过从截图看出实际并非这样。

疑问

1、为什么一个很小的gif图片所需耗时为224ms?

2、其他大的图片为什么响应时间更短?

3、为什么百度首页的html文件加载耗时也很长,它不是“静态”html文件吗?


性能测试 页面请求加载过程 实战讲解

Java SpringBoot框架 示例

背景介绍

        讲解示例从“QA不加班http://www.qabujiaban.com(QA不加班) ”  中抽取部分讲解,QA不加班网站主要为广大的测试人员提供包括但不限于百度网盘、阿里云网盘资源搜索,常用测试工具和开发工具包的资源下载的一个网站,目的在于测试交流和资源汇总。   

        网站作者不是本人,而是一个努力奋斗的同行。偶然的机会让是因为网站名称而相遇,相“杀”相爱最后交流沟通后共同维护该网站。其实就是白嫖别人的服务器和域名,然后帮忙修修改改。

网站首页截图

QA不加班
http://www.qabujiaban.com

“温故而知新”

发起请求到请求完成的响应时间示例图解.png

1、GET请求 响应耗时 请求不带参数

请求路径: {域名}/benjamin/

    1.1    浏览器访问接口 请求捕获响应时间和响应内容

    1.2    浏览器查看接口 请求方法

     1.3    SpringBoot  源码示例

/**
     * 首页
     * @return
     */
    @RequestMapping("/")
    public String index(HttpServletRequest request){
        JSONObject result = new JSONObject();
        result.put("msg", "ok");
        result.put("request url",request.getRequestURL().toString());
        result.put("method", request.getMethod());
        result.put("ipAddress", request.getRemoteAddr());
        result.put("x-client-ip",request.getHeader("x-client-ip"));
        result.put("X-Real-IP",request.getHeader("X-Real-IP"));
        return result.toJSONString();
    }

    1.4    响应耗时 分析

    从上述1.1中可以看到实际请求耗时为5ms(毫秒),因为这个时间为本地调试直接本机访问忽略了大部分网络在传输过程中的耗时,后端代码未做参数请求逻辑判断同时未请求数据耗时,所有响应数据很快。

2、GET请求 响应耗时 带参数

请求路径:{域名}/benjamin/getUserid?id=3

   2.1    浏览器访问接口 请求捕获响应时间和响应内容

    2.2   SpringBoot  源码示例

Controller层

@RequestMapping("/getUserId")
    public User getUserId(Integer id){
        return testMyBatisService.getUserInfo(id);
    }

Service层

    public User getUserInfo(Integer id){
        User  user = testMyBatisMapper.findUserId(id);
        if(user == null){
            return  new User();
        }
        return user;
    }

Maaper层

@Select("select * from user where id = #{id}")
    User findUserId(@Param("id") Integer id);

    2.3    响应耗时 分析

        从上述2.1中可以看到实际请求耗时为82ms(毫秒),页面返回数据大小为242B,本次请求耗时相比1.1的增加16.4倍(本地调试数据并非实际耗时),本次请求耗时长的原因因为请求带了入参后端并处理了数据进行了数据库交互耗时。

2.1请求示例耗时 = 后端服务器处理耗时 + Mysql数据库请求耗时

测试:发现某个问题问开发并反馈问题

开发:我这里本地调试没问题呀?是不是环境不对,版本不对,网络有问题?

测试:……

    2.4    Mysql请求耗时 过程分析

mysql> show tables;
+----------------+
| Tables_in_demo |
+----------------+
| band_bill      |
| blacklist      |
| chat           |
| images         |
| message        |
| message_manage |
| user           |
| web_log        |
+----------------+
8 rows in set (0.10 sec)

mysql> use demo;
Database changed
mysql> select * from user where id=3;
+------+-----------+----------------------------------+-----+-----+-------------------+----------------+---------------------+-----------+-------------+
| id   | username  | password                         | age | sex | administration_id | ip             | create_time         | is_delete | mobile      |
+------+-----------+----------------------------------+-----+-----+-------------------+----------------+---------------------+-----------+-------------+
| 3 | xxxx3*** | df829ac156248a556e0be9372adb8cbc | 18  | 2   |                 1 | 116.234.xx.xxx | 2021-12-22 13:44:18 | 1         | 177017xxxx |
+------+-----------+----------------------------------+-----+-----+-------------------+----------------+---------------------+-----------+-------------+
1 row in set (0.11 sec)

Mysql优化暂不做详细说明如何优化查询耗时?索引优化、分库分区分表、集群等技术点

3、 POST请求 响应耗时 带参数、数据校验、第三方接口查询

请求路径:{域名}/benjamin/Message

请求路径:{域名}/benjamin/verify

    3.1    浏览器访问接口 请求捕获响应时间和响应内容

    3.2   SpringBoot  源码示例

 Controller层

    /**
     * 留言展示和提交留言验证页面
     */
    @RequestMapping("/Message")
    public String Message() {
        return "Message";
    }
   /**
     * 留言验证接口
     */
    @PostMapping(value = "/verify", produces = {"application/json; charset=UTF-8"})
    public Map<String, String> verify(TestVo testVo, ServletWebRequest servletWebRequest, HttpServletRequest request) {

        // 获取用户请求的ip并解析ip所在的省份
        String message_ip = GetIPCity.GetRequestIP(request);
        testVo.setMessage_ip(message_ip);
        // 解析ip  可能存在获取失败的问题修复
        testVo.setMessage_city(GetIPCity.GetRequestCity(message_ip));

        final ImageVerify.ImageCode imageCode = (ImageVerify.ImageCode) sessionStrategy.getAttribute(servletWebRequest, SESSION_KEY_IMAGE_CODE);

        Map<String, String> m = new HashMap<>();

        if (StringUtils.isBlank(testVo.getCode())) {
            m.put("message", "验证码不能为空!");
            return m;
        }

        if (imageCode == null) {
            m.put("message", "验证码不存在!");
            return m;
        }

        if (imageCode.isExpire()) {
            sessionStrategy.removeAttribute(servletWebRequest, SESSION_KEY_IMAGE_CODE);
            m.put("message", "验证码已过期!");
            return m;
        }

        if (!StringUtils.equalsIgnoreCase(imageCode.getCode(), testVo.getCode())) {
            m.put("message", "验证码不正确!");
            return m;
        }

        sessionStrategy.removeAttribute(servletWebRequest, SESSION_KEY_IMAGE_CODE);



        // 评论数据,写入数据库;
        messageService.MessageInsert(testVo);

        m.put("message", "成功");
        return m;

    }

Util层(未做详细代码展示)

--util

    -- GetIPCity.java        // 通过第三方服务高德api解析请求城市信息

    -- ImageVerify.java    // 验证码生成和判断输入是否正常

Service层

    // 添加事务回滚
    @Transactional
    public Message MessageInsert(TestVo testVo){
        String user = testVo.getMessage_user();
        String content = testVo.getMessage_content();

        user = SetHtmlString.setHtmlString(user);
        content = SetHtmlString.setHtmlString(content);

        if (user.length() <= 255){
            messageMapper.MessageInsert(user,
                                        content,
                                        testVo.getMessage_ip(),
                                        testVo.getMessage_city());

        }
        return null;



    }

Mapper层

    // 增加留言
    @Insert(" INSERT INTO message(message_user,message_content,message_ip,message_city) VALUE(#{message_user},#{message_content},#{message_ip},#{message_city})")
    void MessageInsert(@Param("message_user") String message_user,
                       @Param("message_content") String message_content,
                       @Param("message_ip") String message_ip,
                       @Param("message_city") String message_city);

    3.3    响应耗时 分析

        从上述3.1中可以看到实际请求耗时为415ms(毫秒),页面返回数据大小为207B,本次请求耗时相比1.1的增加83倍,同比2.2耗时增加415/82=5倍,本次请求耗时多的原因是因为请求带了入参后端处理:图形验证码校验正确性,第三方高德api请求耗时,Mysql数据请求耗时,服务端处理响应耗时。

3.1请求示例耗时 = 服务器处理耗时 + 图形验证码校验 + 高德api + Mysql数据库请求耗时

4、响应请求耗时 拓展示例

        实际应用项目可能有更为复杂架构交互,影响响应耗时的因素还有很多不便逐一讲解,空余时间自主学习和拓展示例的演示。

        获得实战经验的最佳途径是实践,多从生活和工作项目中吸取经验。

“实践是检验真理的唯一途径”

某大型项目的架构图.png 


结束语

遗忘在角落年久失修的微信公众号图.png