metersphere性能压测执行过程
(1) 首先在controller层,通过RunTestPlanRequest接收请求参数
@PostMapping("/run") public String run(@RequestBody RunTestPlanRequest request)
(2) 在PerformanceTestService中的run中进行具体的逻辑处理,
- 首先根据请求中ID来获取库中存储的测试用例信息(判空和运行状态判断)
final LoadTestWithBLOBs loadTest = loadTestMapper.selectByPrimaryKey(request.getId()); if (request.getUserId() != null) { loadTest.setUserId(request.getUserId()); } if (loadTest == null) { MSException.throwException(Translator.get("run_load_test_not_found") + request.getId()); }
- 后根据查出的用例信息中资源池id,判断此id资源池是否存在和状态有效,
String testResourcePoolId = loadTest.getTestResourcePoolId(); TestResourcePool testResourcePool = testResourcePoolMapper.selectByPrimaryKey(testResourcePoolId); if (testResourcePool == null) { MSException.throwException(Translator.get("test_resource_pool_not_exists")); } if (ResourceStatusEnum.INVALID.name().equals(testResourcePool.getStatus())) { MSException.throwException(Translator.get("test_resource_pool_invalid")); }
- 并检查kafka是否可通
String bootstrapServers = kafkaProperties.getBootstrapServers(); String[] servers = StringUtils.split(bootstrapServers, ","); try { for (String s : servers) { String[] ipAndPort = s.split(":"); //1,建立tcp String ip = ipAndPort[0]; int port = Integer.parseInt(ipAndPort[1]); Socket soc = new Socket(); soc.connect(new InetSocketAddress(ip, port), 1000); // 1s timeout //2.输入内容 String content = "1010"; byte[] bs = content.getBytes(); OutputStream os = soc.getOutputStream(); os.write(bs); //3.关闭 soc.close();
- 然后根据不同的资源池类型,实例化不同的Engine,比如是node节点类型,new DockerTestEngine(loadTest); 若是k8s类型则(Engine) ConstructorUtils.invokeConstructor(kubernetesTestEngineClass,loadTest); 其中如果节点类型实例化,主要做两个工作,一是初始化工作,比如threadNum,JMETER_IMAGE,HEAP,二是从容器获取RestTemplate,用于之后的请求。
final ResourcePoolTypeEnum type = ResourcePoolTypeEnum.valueOf(resourcePool.getType()); if (type == ResourcePoolTypeEnum.NODE) { return new DockerTestEngine(loadTest); } if (type == ResourcePoolTypeEnum.K8S) { try { return (Engine) ConstructorUtils.invokeConstructor(kubernetesTestEngineClass, loadTest);
- 通过startEngine,开始执行用例,首先设置测试报告开始时间等基础信息,然后调用engine中start方法,开始执行,start处理上又分为:
判断当前需要的并发线程是否小于空闲线程数
int totalThreadNum = resourceList.stream() .filter(r -> ResourceStatusEnum.VALID.name().equals(r.getStatus())) .map(r -> JSON.parseObject(r.getConfiguration(), NodeDTO.class).getMaxConcurrency()) .reduce(Integer::sum) .orElse(0); //获取所有有效资源池的最大并发数,并累加 if (threadNum > totalThreadNum - runningSumThreadNum) { MSException.throwException(Translator.get("max_thread_insufficient")); }
- 计算各个资源池最大并发数占总的并发数比例
Object[] resourceRatios = resourceList.stream() .filter(r -> ResourceStatusEnum.VALID.name().equals(r.getStatus())) .map(r -> JSON.parseObject(r.getConfiguration(), NodeDTO.class).getMaxConcurrency()) .map(r -> r * 1.0 / totalThreadNum) .map(r -> String.format("%.2f", r)) .toArray();// 各个资源池最大并发数占总的并发数比例
开始利用资源池进行测试,如 准备启动jmeter容器时需要的环境参数,比如镜像,测试ID,报告ID,topic等,后通过RestTemplate 向node controller发送启动容器请求,并将对应的环境参数传递过去 。node
controller在接收到请求后创建jmeter容器,jmeter容器会根据对应的环境参数去metis平台自动下载jmx, 从而开始压测。
小结: