fix (接口自动化): 优化场景串行执行,避免频繁和数据库交互;增加get请求可加请求体

--bug=1006978 --user=赵勇 【github#6559】http请求,get中带有body的请求执行后,后台服务收到的请求里没有请求体 https://www.tapd.cn/55049933/s/1052908
This commit is contained in:
fit2-zhao 2021-09-28 18:14:59 +08:00 committed by fit2-zhao
parent 74c4c55672
commit 3e1936bc69
5 changed files with 44 additions and 30 deletions

View File

@ -1,7 +1,6 @@
package io.metersphere.api.dto.definition.request.sampler; package io.metersphere.api.dto.definition.request.sampler;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.annotation.JSONType; import com.alibaba.fastjson.annotation.JSONType;
@ -225,8 +224,7 @@ public class MsHTTPSamplerProxy extends MsTestElement {
setSamplerPath(config, httpConfig, sampler); setSamplerPath(config, httpConfig, sampler);
// 请求体 // 请求体处理
if (!StringUtils.equals(this.getMethod(), "GET")) {
if (this.body != null) { if (this.body != null) {
List<KeyValue> bodyParams = this.body.getBodyParams(sampler, this.getId()); List<KeyValue> bodyParams = this.body.getBodyParams(sampler, this.getId());
if (StringUtils.isNotEmpty(this.body.getType()) && "Form Data".equals(this.body.getType())) { if (StringUtils.isNotEmpty(this.body.getType()) && "Form Data".equals(this.body.getType())) {
@ -236,7 +234,6 @@ public class MsHTTPSamplerProxy extends MsTestElement {
sampler.setArguments(httpArguments(bodyParams)); sampler.setArguments(httpArguments(bodyParams));
} }
} }
}
final HashTree httpSamplerTree = tree.add(sampler); final HashTree httpSamplerTree = tree.add(sampler);

View File

@ -56,5 +56,8 @@ public class APIBackendListenerHandler {
if (!MessageCache.reportCache.containsKey(testId) && resultService.getProcessCache().containsKey(testId)) { if (!MessageCache.reportCache.containsKey(testId) && resultService.getProcessCache().containsKey(testId)) {
resultService.getProcessCache().remove(testId); resultService.getProcessCache().remove(testId);
} }
if(StringUtils.isNotEmpty(testId)) {
MessageCache.executionQueue.remove(testId);
}
} }
} }

View File

@ -20,4 +20,7 @@ public class MessageCache {
public static ConcurrentHashMap<String, ApiDefinitionExecResult> batchTestCases = new ConcurrentHashMap<>(); public static ConcurrentHashMap<String, ApiDefinitionExecResult> batchTestCases = new ConcurrentHashMap<>();
// 串行执行队列 KEY=报告ID VALUE=开始时间
public static Map<String, Long> executionQueue = new HashMap<>();
} }

View File

@ -51,7 +51,9 @@ import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest;
import io.metersphere.track.request.testcase.QueryTestPlanRequest; import io.metersphere.track.request.testcase.QueryTestPlanRequest;
import io.metersphere.track.request.testplan.FileOperationRequest; import io.metersphere.track.request.testplan.FileOperationRequest;
import io.metersphere.track.service.TestPlanScenarioCaseService; import io.metersphere.track.service.TestPlanScenarioCaseService;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections4.comparators.FixedOrderComparator;
import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.ExecutorType;
@ -997,11 +999,19 @@ public class ApiAutomationService {
// 生成集成报告 // 生成集成报告
String serialReportId = null; String serialReportId = null;
StringBuilder idStr = new StringBuilder(); ApiScenarioExample example = new ApiScenarioExample();
ids.forEach(item -> { example.createCriteria().andIdIn(ids);
idStr.append("\"").append(item).append("\"").append(","); List<ApiScenarioWithBLOBs> apiScenarios = apiScenarioMapper.selectByExampleWithBLOBs(example);
}); if (request.getConfig() != null && request.getConfig().getMode().equals(RunModeConstants.SERIAL.toString())) {
List<ApiScenarioWithBLOBs> apiScenarios = extApiScenarioMapper.selectByIds(idStr.toString().substring(0, idStr.toString().length() - 1), "\"" + StringUtils.join(ids, ",") + "\""); if (request.getCondition() == null || !request.getCondition().isSelectAll()) {
// 按照id指定顺序排序
FixedOrderComparator<String> fixedOrderComparator = new FixedOrderComparator<String>(ids);
fixedOrderComparator.setUnknownObjectBehavior(FixedOrderComparator.UnknownObjectBehavior.BEFORE);
BeanComparator beanComparator = new BeanComparator("id", fixedOrderComparator);
Collections.sort(apiScenarios, beanComparator);
}
}
// 只有一个场景且没有测试步骤则提示 // 只有一个场景且没有测试步骤则提示
if (apiScenarios != null && apiScenarios.size() == 1 && (apiScenarios.get(0).getStepTotal() == null || apiScenarios.get(0).getStepTotal() == 0)) { if (apiScenarios != null && apiScenarios.size() == 1 && (apiScenarios.get(0).getStepTotal() == null || apiScenarios.get(0).getStepTotal() == 0)) {
MSException.throwException((apiScenarios.get(0).getName() + "" + Translator.get("automation_exec_info"))); MSException.throwException((apiScenarios.get(0).getName() + "" + Translator.get("automation_exec_info")));
@ -1162,6 +1172,7 @@ public class ApiAutomationService {
MessageCache.terminationOrderDeque.remove(key); MessageCache.terminationOrderDeque.remove(key);
break; break;
} }
MessageCache.executionQueue.put(key, System.currentTimeMillis());
reportIds.add(key); reportIds.add(key);
APIScenarioReportResult report = executeQueue.get(key).getReport(); APIScenarioReportResult report = executeQueue.get(key).getReport();
if (StringUtils.isNotEmpty(serialReportId)) { if (StringUtils.isNotEmpty(serialReportId)) {
@ -1193,6 +1204,7 @@ public class ApiAutomationService {
executeEnvParams = hashTreeUtil.mergeParamDataMap(executeEnvParams, envParamsMap); executeEnvParams = hashTreeUtil.mergeParamDataMap(executeEnvParams, envParamsMap);
} catch (Exception e) { } catch (Exception e) {
reportIds.remove(key); reportIds.remove(key);
MessageCache.executionQueue.remove(key);
LogUtil.error("执行终止:" + e.getMessage()); LogUtil.error("执行终止:" + e.getMessage());
break; break;
} }

View File

@ -34,7 +34,7 @@ public class SerialScenarioExecTask<T> implements Callable<T> {
@Override @Override
public T call() { public T call() {
try { try {
if (runModeDataDTO.getReport()!=null && MessageCache.terminationOrderDeque.contains(runModeDataDTO.getReport().getId())) { if (runModeDataDTO.getReport() != null && MessageCache.terminationOrderDeque.contains(runModeDataDTO.getReport().getId())) {
MessageCache.terminationOrderDeque.remove(runModeDataDTO.getReport().getId()); MessageCache.terminationOrderDeque.remove(runModeDataDTO.getReport().getId());
return null; return null;
} }
@ -43,25 +43,24 @@ public class SerialScenarioExecTask<T> implements Callable<T> {
} else { } else {
jMeterService.runLocal(runModeDataDTO.getReport().getId(), runModeDataDTO.getHashTree(), TriggerMode.BATCH.name().equals(request.getTriggerMode()) ? TriggerMode.BATCH.name() : request.getReportId(), request.getRunMode()); jMeterService.runLocal(runModeDataDTO.getReport().getId(), runModeDataDTO.getHashTree(), TriggerMode.BATCH.name().equals(request.getTriggerMode()) ? TriggerMode.BATCH.name() : request.getReportId(), request.getRunMode());
} }
// 轮询查看报告状态最多200次防止死循环 while (MessageCache.executionQueue.containsKey(runModeDataDTO.getReport().getId())) {
int index = 1; long currentSecond = (System.currentTimeMillis() - MessageCache.executionQueue.get(runModeDataDTO.getReport().getId())) / 1000 / 60;
while (index < 200) { // 设置五分钟超时
Thread.sleep(3000); if (currentSecond > 5) {
index++; // 执行失败了恢复报告状态
report = apiScenarioReportMapper.selectByPrimaryKey(runModeDataDTO.getReport().getId()); report = apiScenarioReportMapper.selectByPrimaryKey(runModeDataDTO.getReport().getId());
if (report != null && !report.getStatus().equals(APITestStatus.Running.name())) { if (report != null) {
report.setStatus(APITestStatus.Error.name());
apiScenarioReportMapper.updateByPrimaryKey(report);
}
break; break;
} }
if (runModeDataDTO.getReport()!=null && MessageCache.terminationOrderDeque.contains(runModeDataDTO.getReport().getId())) { if (runModeDataDTO.getReport() != null && MessageCache.terminationOrderDeque.contains(runModeDataDTO.getReport().getId())) {
MessageCache.terminationOrderDeque.remove(runModeDataDTO.getReport().getId()); MessageCache.terminationOrderDeque.remove(runModeDataDTO.getReport().getId());
break; break;
} }
} }
// 执行失败了恢复报告状态 report = apiScenarioReportMapper.selectByPrimaryKey(runModeDataDTO.getReport().getId());
if (index == 200 && report != null && report.getStatus().equals(APITestStatus.Running.name())) {
report.setStatus(APITestStatus.Error.name());
apiScenarioReportMapper.updateByPrimaryKey(report);
}
return (T) report; return (T) report;
} catch (Exception ex) { } catch (Exception ex) {
LogUtil.error(ex); LogUtil.error(ex);