websocet请求性能测试实践总结


虽然之前有进行过一段时间的性能测试,但没有做过websocket请求的性能测试,此次项目用到了websocket请求,在摸索中也踩了一些坑,记录下来,供后续参考。

1、需求内容

notebook建模首先需要创建容器,容器创建好后,就可以发送建模请求,建模请求方式是websocket。本次就需要测试notebook建模的性能指标,比如能够承受最多多少个并发等。

2、实现流程

2.1 生成jobid

1)理想的情况是每个请求(不同用户)可以在不同的容器发送建模请求,就需要调用创建容器时每次入参的jobid不同,所以在前一个job提交接口,就需要生成不同的jobid;生成不同的jobid,需要该接口入参的jobName和jobCode不同,所以生成jobid步骤对入参进行了参数化处理&随机数生成处理。入下图:
在这里插入图片描述
2)请求体内容如下:

{"jobName":"perf_${__Random(1,3000,id)}","projectId":1727,"jobType":7,"runResource":"default","sparkCcolony":"default","fileDir":"default","jobCode":"t0_1544168471${__Random(1,300,id)}"}

3)jobid要作为下一个接口的入参,所以还需要使用正则表达式提取器。
在这里插入图片描述

  • 引用名称:下个请求将要引用到的变量名。
  • 正则表达式:提取你想要内容的正则表达式,小括号()表示提取,也就是说对于你想要提取的内容用它括起来。
  • 模板:使用提取到的第几个值。因为可能有多个值匹配,所以要使用模板。从1开始匹配,依次类推。这里只有一个,所以填写 1 1 1即可。
  • 匹配数字:表示如何取值。0表示随机取值,1表示全部取值。这里只有一个,填1即可。
  • 缺省值:表示参数没有取到值的话,默认给它的值。一般不填。

这里其中jobID就是下一个请求要引入的变量。

2.2 调用创建容器接口

生成jobid后,就可以去创建容器了。请求如下:
在这里插入图片描述
后续我们要使用到该接口返回参数notebookurl,但该url有ip,port以及path,下一个接口只需要使用ip和port,所以要使用正则提取出该字段,然后对url进行ip,port提取。
正则提取:
在这里插入图片描述

添加后置处理器:
在这里插入图片描述
代码块:

String ip= vars.get("notebookUrl");
log.info("首次进入beanshell。");

if (ip != null && !"null".equals(ip)){
	log.info("ip的初始值为:" + ip);
	ip = ip.substring(7);
	log.info("ip的值为:" + ip);
	ip = ip.substring(ip.indexOf(":")+1);
	log.info("ip的值为:"+ip);
	ip = ip.substring(ip.indexOf("/")+1,ip.lastIndexOf("/"));
	log.info("ip的值为:"+ip);
	ip = ip.substring(0,ip.lastIndexOf("/"));
	log.info("ip的最终值为:"+ip);
	vars.put("notebookUrl",ip);
}else{
	log.info("容器未创建,需要重新调用创建容器接口。");
	vars.put("notebookUrl", "null");
}

为何要加null判断?因为有时候容器已经事先创建成功了,就不需要进行截取了。

2.3 确定容器创建成功

创建容器接口是一个异步请求,所以我们要循环调用info查询接口,判断容器是否创建成功。使用while控制器事先,只有ip为空时会循环查询,条件如下:
在这里插入图片描述
同样需要对相应的结果进行抽取,获取notebookurl;以及后置处理,获取截取后的ip和port,但是此时的后置处理逻辑和上个有所不同。
正则提取:
在这里插入图片描述
ip截取后置处理:
在这里插入图片描述

  String ip= vars.get("notebookUrl");
log.info("轮询/zero/job/info接口,查询该接口是否有notebookUrl返回,直到返回notebookUrl不为空后退出。");

if (ip != null && !"null".equals(ip)){
	log.info("轮询后ip的初始值为:" + ip);
	ip = ip.substring(7);
	log.info("轮询后ip的值为:" + ip);
	ip = ip.substring(ip.indexOf(":")+1);
	log.info("轮询后ip的值为:"+ip);
	ip = ip.substring(ip.indexOf("/")+1,ip.lastIndexOf("/"));
	log.info("轮询后ip的值为:"+ip);
	ip = ip.substring(0,ip.lastIndexOf("/"));
	log.info("轮询后ip的最终值为:"+ip);
	vars.put("notebookUrl",ip);
}

2.4 创建kernel接口

该接口会生成websocket请求的kernelId和sessionID,请求很简单,稍微复杂的是需要对结果进行提取,均使用后置处理器提取。
sessionId,随机生成32位16进制数:

  import java.util.Random;

public class randomHexString {
    public static String randomImpl(int len) {
        try {
            StringBuffer result = new StringBuffer();
            for (int i = 0; i < len; i++) {
                result.append(Integer.toHexString(new Random().nextInt(16)));
            }
            String sid = result.toString().toUpperCase();
            log.info("生成的32位16进制数sessionid是:" + sid);
            return sid;


        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();

        }
        return null;
    }
}

int len = 32;
String sid = randomHexString.randomImpl(len);
vars.put("sid",sid);

kernelId从返回response中提取:

import org.json.*;  

String response_data = prev.getResponseDataAsString(); 

JSONObject data_obj = new JSONObject(response_data); 

String diaryList_str = data_obj.get("kernel").get("id").toString(); 
log.info("获取到的kernelID为:" + diaryList_str); 
vars.put("kernelID",diaryList_str);

2.5 发送建模请求

每个建模请求还有一个需要随机生成的数字,msgID,需要在发送请求前用前置处理器生成;同时通过wiershark以及chrome自带浏览器的功能,检测到建模会发送3个websocket请求。
1)建模请求1前置处理:

   import java.util.Random;

public class randomHexString {
    public static String randomImpl(int len) {
        try {
            StringBuffer result = new StringBuffer();
            for (int i = 0; i < len; i++) {
                result.append(Integer.toHexString(new Random().nextInt(16)));
            }
            String sid = result.toString().toUpperCase();
            log.info("生成的32位16进制数msgId1是:" + sid);
            return sid;


        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();

        }
        return null;
    }
}

int len = 32;
String msgId1 = randomHexString.randomImpl(len);
vars.put("msgId1",msgId1);

2)建模请求1请求参数:
在这里插入图片描述

 {"header":{"msg_id":"${msgId1}","username":"username","session":"${sid}","msg_type":"kernel_info_request","version":"5.0"},"metadata":{},"content":{},"buffers":[],"parent_header":{},"channel":"shell"}

其他两个请求同上,不一一赘述;后续再添加查看结果树,以及汇总报告等监听,即完成本次需求。

3、知识总结

本次性能脚本测试,了解了之前没有使用过debug sample,前置脚本,后置脚本书写逻辑,正则表达式的抽取、变量参数化以及while控制器脚本书写逻辑(while控制器的空必须是"null")。这些细节内容将后续单列总结。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值