refactor: 重构传递测试文件的方式
This commit is contained in:
parent
db472877b4
commit
be95c69af5
|
@ -379,6 +379,12 @@
|
|||
<artifactId>reflections8</artifactId>
|
||||
<version>0.11.7</version>
|
||||
</dependency>
|
||||
<!-- k8s client -->
|
||||
<dependency>
|
||||
<groupId>io.fabric8</groupId>
|
||||
<artifactId>kubernetes-client</artifactId>
|
||||
<version>4.13.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -16,4 +16,5 @@ public class JmeterProperties {
|
|||
|
||||
private String home;
|
||||
|
||||
private String heap = "-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m";
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ public class ShiroConfig implements EnvironmentAware {
|
|||
ShiroUtils.loadBaseFilterChain(filterChainDefinitionMap);
|
||||
filterChainDefinitionMap.put("/display/info", "anon");
|
||||
filterChainDefinitionMap.put("/display/file/**", "anon");
|
||||
filterChainDefinitionMap.put("/jmeter/download/**", "anon");
|
||||
filterChainDefinitionMap.put("/**", "apikey, authc");
|
||||
return shiroFilterFactoryBean;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package io.metersphere.performance.controller;
|
||||
|
||||
|
||||
import io.metersphere.performance.service.JmeterFileService;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("jmeter")
|
||||
public class JmeterFileController {
|
||||
@Resource
|
||||
private JmeterFileService jmeterFileService;
|
||||
|
||||
@GetMapping("download")
|
||||
public ResponseEntity<byte[]> downloadJmeterFiles(@RequestParam("testId") String testId, @RequestParam("resourceId") String resourceId,
|
||||
@RequestParam("ratio") double ratio, @RequestParam("startTime") long startTime,
|
||||
@RequestParam("reportId") String reportId, @RequestParam("resourceIndex") int resourceIndex,
|
||||
@RequestParam("threadNum") int threadNum) {
|
||||
byte[] bytes = jmeterFileService.downloadZip(testId, resourceId, ratio, startTime, reportId, resourceIndex, threadNum);
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.parseMediaType("application/octet-stream"))
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + testId + ".zip\"")
|
||||
.body(bytes);
|
||||
}
|
||||
|
||||
}
|
|
@ -15,7 +15,6 @@ public class EngineContext {
|
|||
private Integer resourceIndex;
|
||||
private Map<String, Object> properties = new HashMap<>();
|
||||
private Map<String, String> testData = new HashMap<>();
|
||||
private Map<String, String> env = new HashMap<>();
|
||||
private Map<String, byte[]> testJars = new HashMap<>();
|
||||
|
||||
public String getTestId() {
|
||||
|
@ -50,14 +49,6 @@ public class EngineContext {
|
|||
this.properties.putAll(props);
|
||||
}
|
||||
|
||||
public Map<String, String> getEnv() {
|
||||
return env;
|
||||
}
|
||||
|
||||
public void setEnv(Map<String, String> env) {
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
public Object getProperty(String key) {
|
||||
return this.properties.get(key);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import io.metersphere.commons.constants.FileType;
|
|||
import io.metersphere.commons.constants.ResourcePoolTypeEnum;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.config.KafkaProperties;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import io.metersphere.performance.engine.docker.DockerTestEngine;
|
||||
import io.metersphere.performance.parse.EngineSourceParser;
|
||||
|
@ -34,7 +33,6 @@ import java.util.stream.Collectors;
|
|||
public class EngineFactory {
|
||||
private static FileService fileService;
|
||||
private static TestResourcePoolService testResourcePoolService;
|
||||
private static KafkaProperties kafkaProperties;
|
||||
private static Class<? extends KubernetesTestEngine> kubernetesTestEngineClass;
|
||||
|
||||
static {
|
||||
|
@ -99,13 +97,6 @@ public class EngineFactory {
|
|||
engineContext.setStartTime(startTime);
|
||||
engineContext.setReportId(reportId);
|
||||
engineContext.setResourceIndex(resourceIndex);
|
||||
HashMap<String, String> env = new HashMap<String, String>() {{
|
||||
put("BOOTSTRAP_SERVERS", kafkaProperties.getBootstrapServers());
|
||||
put("LOG_TOPIC", kafkaProperties.getLog().getTopic());
|
||||
put("REPORT_ID", reportId);
|
||||
put("RESOURCE_ID", resourceId);
|
||||
}};
|
||||
engineContext.setEnv(env);
|
||||
|
||||
if (StringUtils.isNotEmpty(loadTest.getLoadConfiguration())) {
|
||||
final JSONArray jsonArray = JSONObject.parseArray(loadTest.getLoadConfiguration());
|
||||
|
@ -197,9 +188,4 @@ public class EngineFactory {
|
|||
public void setTestResourcePoolService(TestResourcePoolService testResourcePoolService) {
|
||||
EngineFactory.testResourcePoolService = testResourcePoolService;
|
||||
}
|
||||
|
||||
@Resource
|
||||
public void setKafkaProperties(KafkaProperties kafkaProperties) {
|
||||
EngineFactory.kafkaProperties = kafkaProperties;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,17 +6,19 @@ import io.metersphere.base.domain.TestResource;
|
|||
import io.metersphere.commons.constants.ResourceStatusEnum;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.config.KafkaProperties;
|
||||
import io.metersphere.controller.ResultHolder;
|
||||
import io.metersphere.dto.BaseSystemConfigDTO;
|
||||
import io.metersphere.dto.NodeDTO;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import io.metersphere.performance.engine.AbstractEngine;
|
||||
import io.metersphere.performance.engine.EngineContext;
|
||||
import io.metersphere.performance.engine.EngineFactory;
|
||||
import io.metersphere.performance.engine.docker.request.TestRequest;
|
||||
import io.metersphere.performance.engine.request.StartTestRequest;
|
||||
import io.metersphere.service.SystemParameterService;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class DockerTestEngine extends AbstractEngine {
|
||||
|
@ -60,38 +62,38 @@ public class DockerTestEngine extends AbstractEngine {
|
|||
}
|
||||
|
||||
private void runTest(TestResource resource, double ratio, int resourceIndex) {
|
||||
EngineContext context = null;
|
||||
try {
|
||||
context = EngineFactory.createContext(loadTest, resource.getId(), ratio, this.getStartTime(), this.getReportId(), resourceIndex);
|
||||
} catch (MSException e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
MSException.throwException(e);
|
||||
}
|
||||
|
||||
String configuration = resource.getConfiguration();
|
||||
NodeDTO node = JSON.parseObject(configuration, NodeDTO.class);
|
||||
String nodeIp = node.getIp();
|
||||
Integer port = node.getPort();
|
||||
String testId = context.getTestId();
|
||||
String content = context.getContent();
|
||||
|
||||
BaseSystemConfigDTO baseInfo = CommonBeanFactory.getBean(SystemParameterService.class).getBaseInfo();
|
||||
KafkaProperties kafkaProperties = CommonBeanFactory.getBean(KafkaProperties.class);
|
||||
String metersphereUrl = "http://localhost:8081";
|
||||
if (baseInfo != null) {
|
||||
metersphereUrl = baseInfo.getUrl();
|
||||
}
|
||||
|
||||
Map<String, String> env = new HashMap<>();
|
||||
env.put("RATIO", "" + ratio);
|
||||
env.put("RESOURCE_INDEX", "" + resourceIndex);
|
||||
env.put("METERSPHERE_URL", metersphereUrl);
|
||||
env.put("START_TIME", "" + this.getStartTime());
|
||||
env.put("TEST_ID", this.loadTest.getId());
|
||||
env.put("REPORT_ID", this.getReportId());
|
||||
env.put("BOOTSTRAP_SERVERS", kafkaProperties.getBootstrapServers());
|
||||
env.put("LOG_TOPIC", kafkaProperties.getLog().getTopic());
|
||||
env.put("RESOURCE_ID", resource.getId());
|
||||
env.put("THREAD_NUM", "" + threadNum);
|
||||
|
||||
|
||||
StartTestRequest startTestRequest = new StartTestRequest();
|
||||
startTestRequest.setImage(JMETER_IMAGE);
|
||||
startTestRequest.setEnv(env);
|
||||
|
||||
String uri = String.format(BASE_URL + "/jmeter/container/start", nodeIp, port);
|
||||
|
||||
TestRequest testRequest = new TestRequest();
|
||||
testRequest.setSize(1);
|
||||
testRequest.setTestId(testId);
|
||||
testRequest.setReportId(getReportId());
|
||||
testRequest.setFileString(content);
|
||||
testRequest.setImage(JMETER_IMAGE);
|
||||
testRequest.setTestData(context.getTestData());
|
||||
testRequest.setTestJars(context.getTestJars());
|
||||
testRequest.setEnv(context.getEnv());
|
||||
|
||||
|
||||
ResultHolder result = restTemplate.postForObject(uri, testRequest, ResultHolder.class);
|
||||
ResultHolder result = restTemplate.postForObject(uri, startTestRequest, ResultHolder.class);
|
||||
if (result == null) {
|
||||
MSException.throwException(Translator.get("start_engine_fail"));
|
||||
}
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
package io.metersphere.performance.engine.docker.request;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class BaseRequest {
|
||||
private String testId;
|
||||
private String reportId;
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package io.metersphere.performance.engine.docker.request;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class TestRequest extends BaseRequest {
|
||||
private int size;
|
||||
private String fileString;
|
||||
private String image;
|
||||
private Map<String, String> testData = new HashMap<>();
|
||||
private Map<String, String> env = new HashMap<>();
|
||||
private Map<String, byte[]> testJars = new HashMap<>();
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package io.metersphere.performance.engine.request;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class BaseRequest {
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package io.metersphere.performance.engine.request;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class StartTestRequest {
|
||||
private String image;
|
||||
private Map<String, String> env = new HashMap<>();
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package io.metersphere.performance.engine.request;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class StopTestRequest {
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
package io.metersphere.performance.service;
|
||||
|
||||
|
||||
import com.alibaba.excel.util.CollectionUtils;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.base.domain.LoadTestWithBLOBs;
|
||||
import io.metersphere.base.mapper.LoadTestMapper;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.performance.engine.EngineContext;
|
||||
import io.metersphere.performance.engine.EngineFactory;
|
||||
import org.apache.commons.lang3.SerializationUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
@Service
|
||||
public class JmeterFileService {
|
||||
|
||||
@Resource
|
||||
private LoadTestMapper loadTestMapper;
|
||||
|
||||
public byte[] downloadZip(String testId, String resourceId, double ratio, long startTime, String reportId, int resourceIndex, int threadNum) {
|
||||
try {
|
||||
LoadTestWithBLOBs loadTest = loadTestMapper.selectByPrimaryKey(testId);
|
||||
// deep copy
|
||||
LoadTestWithBLOBs subTest = SerializationUtils.clone(loadTest);
|
||||
setThreadNum(subTest, threadNum);
|
||||
EngineContext context = EngineFactory.createContext(subTest, resourceId, ratio, startTime, reportId, resourceIndex);
|
||||
return zipFilesToByteArray(context);
|
||||
} catch (MSException e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
MSException.throwException(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void setThreadNum(LoadTestWithBLOBs t, Integer limit) {
|
||||
String loadConfiguration = t.getLoadConfiguration();
|
||||
JSONArray jsonArray = JSON.parseArray(loadConfiguration);
|
||||
for (int i = 0; i < jsonArray.size(); i++) {
|
||||
if (jsonArray.get(i) instanceof Map) {
|
||||
JSONObject o = jsonArray.getJSONObject(i);
|
||||
if (StringUtils.equals(o.getString("key"), "TargetLevel")) {
|
||||
o.put("value", limit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (jsonArray.get(i) instanceof List) {
|
||||
JSONArray o = jsonArray.getJSONArray(i);
|
||||
for (int j = 0; j < o.size(); j++) {
|
||||
JSONObject b = o.getJSONObject(j);
|
||||
if (StringUtils.equals(b.getString("key"), "TargetLevel")) {
|
||||
b.put("value", limit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 设置线程数
|
||||
t.setLoadConfiguration(jsonArray.toJSONString());
|
||||
}
|
||||
|
||||
private byte[] zipFilesToByteArray(EngineContext context) throws IOException {
|
||||
String testId = context.getTestId();
|
||||
String fileName = testId + ".jmx";
|
||||
|
||||
Map<String, byte[]> files = new HashMap<>();
|
||||
|
||||
// 每个测试生成一个文件夹
|
||||
files.put(fileName, context.getContent().getBytes(StandardCharsets.UTF_8));
|
||||
// 保存测试数据文件
|
||||
Map<String, String> testData = context.getTestData();
|
||||
if (!CollectionUtils.isEmpty(testData)) {
|
||||
for (String k : testData.keySet()) {
|
||||
String v = testData.get(k);
|
||||
files.put("k", v.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
|
||||
// 保存 byte[] jar
|
||||
Map<String, byte[]> jarFiles = context.getTestJars();
|
||||
if (!CollectionUtils.isEmpty(jarFiles)) {
|
||||
for (String k : jarFiles.keySet()) {
|
||||
byte[] v = jarFiles.get(k);
|
||||
files.put("k", v);
|
||||
}
|
||||
}
|
||||
|
||||
return listBytesToZip(files);
|
||||
}
|
||||
|
||||
|
||||
private byte[] listBytesToZip(Map<String, byte[]> mapReport) throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ZipOutputStream zos = new ZipOutputStream(baos);
|
||||
for (Map.Entry<String, byte[]> report : mapReport.entrySet()) {
|
||||
ZipEntry entry = new ZipEntry(report.getKey());
|
||||
entry.setSize(report.getValue().length);
|
||||
zos.putNextEntry(entry);
|
||||
zos.write(report.getValue());
|
||||
}
|
||||
zos.closeEntry();
|
||||
zos.close();
|
||||
return baos.toByteArray();
|
||||
}
|
||||
}
|
|
@ -1 +1 @@
|
|||
Subproject commit b5643ac73fb4a2db3f11b23a81848990d8e78703
|
||||
Subproject commit c04791219ce92fd77c7f5f18a3f625f2083194b0
|
Loading…
Reference in New Issue