diff --git a/backend/src/main/java/io/metersphere/api/dto/RunRequest.java b/backend/src/main/java/io/metersphere/api/dto/RunRequest.java index f9425b3c08..cb6216bbbd 100644 --- a/backend/src/main/java/io/metersphere/api/dto/RunRequest.java +++ b/backend/src/main/java/io/metersphere/api/dto/RunRequest.java @@ -8,6 +8,7 @@ import lombok.Setter; @Setter public class RunRequest { private String testId; + private String poolId; // api / case 或有这个属性值 private String reportId; private String url; diff --git a/backend/src/main/java/io/metersphere/api/jmeter/JMeterService.java b/backend/src/main/java/io/metersphere/api/jmeter/JMeterService.java index 791f97bc71..32e4e11f84 100644 --- a/backend/src/main/java/io/metersphere/api/jmeter/JMeterService.java +++ b/backend/src/main/java/io/metersphere/api/jmeter/JMeterService.java @@ -7,13 +7,20 @@ import io.metersphere.api.dto.scenario.request.BodyFile; import io.metersphere.api.service.ApiScenarioReportService; import io.metersphere.base.domain.JarConfig; import io.metersphere.base.domain.TestResource; +import io.metersphere.base.domain.TestResourcePool; +import io.metersphere.base.mapper.TestResourcePoolMapper; import io.metersphere.commons.constants.ApiRunMode; +import io.metersphere.commons.constants.ResourcePoolTypeEnum; import io.metersphere.commons.exception.MSException; -import io.metersphere.commons.utils.*; +import io.metersphere.commons.utils.CommonBeanFactory; +import io.metersphere.commons.utils.CompressUtils; +import io.metersphere.commons.utils.LogUtil; import io.metersphere.config.JmeterProperties; import io.metersphere.dto.BaseSystemConfigDTO; import io.metersphere.dto.NodeDTO; import io.metersphere.i18n.Translator; +import io.metersphere.performance.engine.Engine; +import io.metersphere.performance.engine.EngineFactory; import io.metersphere.service.JarConfigService; import io.metersphere.service.SystemParameterService; import org.apache.commons.collections.CollectionUtils; @@ -54,6 +61,8 @@ public class JMeterService { ResourcePoolCalculation resourcePoolCalculation; @Resource private RestTemplate restTemplate; + @Resource + private TestResourcePoolMapper testResourcePoolMapper; @PostConstruct public void init() { @@ -311,42 +320,48 @@ public class JMeterService { public void runTest(String testId, String reportId, String runMode, String testPlanScenarioId, RunModeConfig config) { // 获取可以执行的资源池 String resourcePoolId = config.getResourcePoolId(); - TestResource testResource = resourcePoolCalculation.getPool(resourcePoolId); - - String configuration = testResource.getConfiguration(); - NodeDTO node = JSON.parseObject(configuration, NodeDTO.class); - String nodeIp = node.getIp(); - Integer port = node.getPort(); - BaseSystemConfigDTO baseInfo = CommonBeanFactory.getBean(SystemParameterService.class).getBaseInfo(); - // 占位符 - String metersphereUrl = "http://localhost:8081"; - if (baseInfo != null) { - metersphereUrl = baseInfo.getUrl(); + RunRequest runRequest = new RunRequest(); + runRequest.setTestId(testId); + if (ApiRunMode.API_PLAN.name().equals(runMode)) { + runRequest.setReportId(reportId); } - try { - RunRequest runRequest = new RunRequest(); - runRequest.setTestId(testId); - if (ApiRunMode.API_PLAN.name().equals(runMode)) { - runRequest.setReportId(reportId); + runRequest.setPoolId(resourcePoolId); + // 占位符 + String platformUrl = "http://localhost:8081"; + if (baseInfo != null) { + platformUrl = baseInfo.getUrl(); + } + platformUrl += "/api/jmeter/download?testId=" + testId + "&reportId=" + reportId + "&testPlanScenarioId" + "&runMode=" + runMode; + if (StringUtils.isNotEmpty(testPlanScenarioId)) { + platformUrl += "=" + testPlanScenarioId; + } + runRequest.setUrl(platformUrl); + runRequest.setRunMode(runMode); + // 如果是K8S调用 + TestResourcePool pool = testResourcePoolMapper.selectByPrimaryKey(resourcePoolId); + if (pool != null && pool.getApi() && pool.getType().equals(ResourcePoolTypeEnum.K8S.name())) { + final Engine engine = EngineFactory.createApiEngine(runRequest); + engine.start(); + } else { + TestResource testResource = resourcePoolCalculation.getPool(resourcePoolId); + String configuration = testResource.getConfiguration(); + NodeDTO node = JSON.parseObject(configuration, NodeDTO.class); + String nodeIp = node.getIp(); + Integer port = node.getPort(); + try { + String uri = String.format(BASE_URL + "/jmeter/api/start", nodeIp, port); + ResponseEntity result = restTemplate.postForEntity(uri, runRequest, String.class); + if (result == null || !StringUtils.equals("SUCCESS", result.getBody())) { + // 清理零时报告 + ApiScenarioReportService apiScenarioReportService = CommonBeanFactory.getBean(ApiScenarioReportService.class); + apiScenarioReportService.delete(reportId); + MSException.throwException("执行失败:" + result); + } + } catch (Exception e) { + e.printStackTrace(); + MSException.throwException(e.getMessage()); } - metersphereUrl += "/api/jmeter/download?testId=" + testId + "&reportId=" + reportId + "&testPlanScenarioId" + "&runMode=" + runMode; - if (StringUtils.isNotEmpty(testPlanScenarioId)) { - metersphereUrl += "=" + testPlanScenarioId; - } - runRequest.setUrl(metersphereUrl); - runRequest.setRunMode(runMode); - String uri = String.format(BASE_URL + "/jmeter/api/start", nodeIp, port); - ResponseEntity result = restTemplate.postForEntity(uri, runRequest, String.class); - if (result == null || !StringUtils.equals("SUCCESS", result.getBody())) { - // 清理零时报告 - ApiScenarioReportService apiScenarioReportService = CommonBeanFactory.getBean(ApiScenarioReportService.class); - apiScenarioReportService.delete(reportId); - MSException.throwException("执行失败:" + result); - } - } catch (Exception e) { - e.printStackTrace(); - MSException.throwException(e.getMessage()); } } } diff --git a/backend/src/main/java/io/metersphere/performance/engine/AbstractEngine.java b/backend/src/main/java/io/metersphere/performance/engine/AbstractEngine.java index 96a0739553..3476c87552 100644 --- a/backend/src/main/java/io/metersphere/performance/engine/AbstractEngine.java +++ b/backend/src/main/java/io/metersphere/performance/engine/AbstractEngine.java @@ -3,6 +3,7 @@ package io.metersphere.performance.engine; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import io.metersphere.api.dto.RunRequest; import io.metersphere.base.domain.LoadTestWithBLOBs; import io.metersphere.base.domain.TestResource; import io.metersphere.base.domain.TestResourcePool; @@ -32,7 +33,6 @@ public abstract class AbstractEngine implements Engine { protected PerformanceTestService performanceTestService; protected Integer threadNum; protected List resourceList; - private final TestResourcePoolService testResourcePoolService; private final TestResourceService testResourceService; @@ -45,7 +45,39 @@ public abstract class AbstractEngine implements Engine { this.startTime = System.currentTimeMillis(); this.reportId = UUID.randomUUID().toString(); } - + protected void initApiConfig(RunRequest runRequest) { + String resourcePoolId = runRequest.getPoolId(); + TestResourcePool resourcePool = testResourcePoolService.getResourcePool(resourcePoolId); + if (resourcePool == null || StringUtils.equals(resourcePool.getStatus(), ResourceStatusEnum.DELETE.name())) { + MSException.throwException("Resource Pool is empty"); + } + if (!ResourcePoolTypeEnum.K8S.name().equals(resourcePool.getType()) + && !ResourcePoolTypeEnum.NODE.name().equals(resourcePool.getType())) { + MSException.throwException("Invalid Resource Pool type."); + } + if (!StringUtils.equals(resourcePool.getStatus(), ResourceStatusEnum.VALID.name())) { + MSException.throwException("Resource Pool Status is not VALID"); + } + // image + String image = resourcePool.getImage(); + if (StringUtils.isNotEmpty(image)) { + JMETER_IMAGE = image; + } + // heap + String heap = resourcePool.getHeap(); + if (StringUtils.isNotEmpty(heap)) { + HEAP = heap; + } + // gc_algo + String gcAlgo = resourcePool.getGcAlgo(); + if (StringUtils.isNotEmpty(gcAlgo)) { + GC_ALGO = gcAlgo; + } + this.resourceList = testResourceService.getResourcesByPoolId(resourcePool.getId()); + if (CollectionUtils.isEmpty(this.resourceList)) { + MSException.throwException("Test Resource is empty"); + } + } protected void init(LoadTestWithBLOBs loadTest) { if (loadTest == null) { MSException.throwException("LoadTest is null."); diff --git a/backend/src/main/java/io/metersphere/performance/engine/EngineFactory.java b/backend/src/main/java/io/metersphere/performance/engine/EngineFactory.java index 86adc07628..1c0e0e7c8f 100644 --- a/backend/src/main/java/io/metersphere/performance/engine/EngineFactory.java +++ b/backend/src/main/java/io/metersphere/performance/engine/EngineFactory.java @@ -3,6 +3,7 @@ package io.metersphere.performance.engine; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import io.metersphere.Application; +import io.metersphere.api.dto.RunRequest; import io.metersphere.base.domain.FileContent; import io.metersphere.base.domain.FileMetadata; import io.metersphere.base.domain.LoadTestWithBLOBs; @@ -88,6 +89,15 @@ public class EngineFactory { return null; } + public static Engine createApiEngine(RunRequest runRequest) { + try { + return (Engine) ConstructorUtils.invokeConstructor(kubernetesTestEngineClass, runRequest); + } catch (Exception e) { + LogUtil.error(e); + return null; + } + } + public static EngineContext createContext(LoadTestWithBLOBs loadTest, double[] ratios, String reportId, int resourceIndex) { final List fileMetadataList = performanceTestService.getFileMetadataByTestId(loadTest.getId()); if (org.springframework.util.CollectionUtils.isEmpty(fileMetadataList)) {