feat(性能测试): 高级配置支持域名绑定

This commit is contained in:
Captain.B 2021-07-22 14:39:22 +08:00 committed by 刘瑞斌
parent 7a4302b291
commit c0b3a961a5
3 changed files with 209 additions and 204 deletions

View File

@ -158,23 +158,12 @@ public class EngineFactory {
{"timeout":10,"statusCode":["302","301"],"params":[{"name":"param1","enable":true,"value":"0","edit":false}],"domains":[{"domain":"baidu.com","enable":true,"ip":"127.0.0.1","edit":false}]}
*/
Map<String, byte[]> testResourceFiles = new HashMap<>();
StringBuilder props = new StringBuilder("# JMeter Properties\n");
if (StringUtils.isNotEmpty(loadTest.getAdvancedConfiguration())) {
JSONObject advancedConfiguration = JSONObject.parseObject(loadTest.getAdvancedConfiguration());
engineContext.addProperties(advancedConfiguration);
JSONArray properties = advancedConfiguration.getJSONArray("properties");
if (properties != null) {
for (int i = 0; i < properties.size(); i++) {
JSONObject prop = properties.getJSONObject(i);
if (!prop.getBoolean("enable")) {
continue;
}
props.append(prop.getString("name")).append("=").append(prop.getString("value")).append("\n");
}
}
}
byte[] props = getJMeterProperties(loadTest, engineContext);
byte[] hosts = getDNSConfig(loadTest, engineContext);
// JMeter Properties
testResourceFiles.put("ms.properties", props.toString().getBytes(StandardCharsets.UTF_8));
testResourceFiles.put("ms.properties", props);
// DNS
testResourceFiles.put("hosts", hosts);
final EngineSourceParser engineSourceParser = EngineSourceParserFactory.createEngineSourceParser(engineContext.getFileType());
@ -204,6 +193,44 @@ public class EngineFactory {
return engineContext;
}
private static byte[] getDNSConfig(LoadTestWithBLOBs loadTest, EngineContext engineContext) {
StringBuilder dns = new StringBuilder("# DNS Config\n");
if (StringUtils.isNotEmpty(loadTest.getAdvancedConfiguration())) {
JSONObject advancedConfiguration = JSONObject.parseObject(loadTest.getAdvancedConfiguration());
engineContext.addProperties(advancedConfiguration);
JSONArray domains = advancedConfiguration.getJSONArray("domains");
if (domains != null) {
for (int i = 0; i < domains.size(); i++) {
JSONObject prop = domains.getJSONObject(i);
if (!prop.getBoolean("enable")) {
continue;
}
dns.append(prop.getString("ip")).append(" ").append(prop.getString("domain")).append("\n");
}
}
}
return dns.toString().getBytes(StandardCharsets.UTF_8);
}
private static byte[] getJMeterProperties(LoadTestWithBLOBs loadTest, EngineContext engineContext) {
StringBuilder props = new StringBuilder("# JMeter Properties\n");
if (StringUtils.isNotEmpty(loadTest.getAdvancedConfiguration())) {
JSONObject advancedConfiguration = JSONObject.parseObject(loadTest.getAdvancedConfiguration());
engineContext.addProperties(advancedConfiguration);
JSONArray properties = advancedConfiguration.getJSONArray("properties");
if (properties != null) {
for (int i = 0; i < properties.size(); i++) {
JSONObject prop = properties.getJSONObject(i);
if (!prop.getBoolean("enable")) {
continue;
}
props.append(prop.getString("name")).append("=").append(prop.getString("value")).append("\n");
}
}
}
return props.toString().getBytes(StandardCharsets.UTF_8);
}
public static byte[] mergeJmx(List<FileMetadata> jmxFiles) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

View File

@ -41,7 +41,6 @@ public class JmeterDocumentParser implements DocumentParser {
private final static String SETUP_THREAD_GROUP = "SetupThreadGroup";
private final static String BACKEND_LISTENER = "BackendListener";
private final static String CONFIG_TEST_ELEMENT = "ConfigTestElement";
private final static String DNS_CACHE_MANAGER = "DNSCacheManager";
private final static String ARGUMENTS = "Arguments";
private final static String RESPONSE_ASSERTION = "ResponseAssertion";
private final static String HTTP_SAMPLER_PROXY = "HTTPSamplerProxy";
@ -96,7 +95,6 @@ public class JmeterDocumentParser implements DocumentParser {
parseHashTree(ele);
} else if (nodeNameEquals(ele, TEST_PLAN)) {
processCheckoutConfigTestElement(ele);
processCheckoutDnsCacheManager(ele);
processCheckoutArguments(ele);
processCheckoutResponseAssertion(ele);
processCheckoutSerializeThreadgroups(ele);
@ -118,9 +116,6 @@ public class JmeterDocumentParser implements DocumentParser {
processBackendListener(ele);
} else if (nodeNameEquals(ele, CONFIG_TEST_ELEMENT)) {
processConfigTestElement(ele);
} else if (nodeNameEquals(ele, DNS_CACHE_MANAGER)) {
// todo dns cache manager bug: https://bz.apache.org/bugzilla/show_bug.cgi?id=63858
// processDnsCacheManager(ele);
} else if (nodeNameEquals(ele, ARGUMENTS)) {
processArguments(ele);
} else if (nodeNameEquals(ele, RESPONSE_ASSERTION)) {
@ -461,59 +456,6 @@ public class JmeterDocumentParser implements DocumentParser {
hashTree.appendChild(document.createElement(HASH_TREE_ELEMENT));
}
private void processCheckoutDnsCacheManager(Element ele) {
if (context.getProperty("domains") == null || JSON.parseArray(context.getProperty("domains").toString()).size() == 0) {
return;
}
Node hashTree = ele.getNextSibling();
while (!(hashTree instanceof Element)) {
hashTree = hashTree.getNextSibling();
}
NodeList childNodes = hashTree.getChildNodes();
for (int i = 0, size = childNodes.getLength(); i < size; i++) {
Node item = childNodes.item(i);
if (nodeNameEquals(item, DNS_CACHE_MANAGER)) {
// 已经存在不再添加
return;
}
}
/*
<DNSCacheManager guiclass="DNSCachePanel" testclass="DNSCacheManager" testname="DNS Cache Manager" enabled="true">
<collectionProp name="DNSCacheManager.servers"/>
<collectionProp name="DNSCacheManager.hosts">
<elementProp name="baiud.com" elementType="StaticHost">
<stringProp name="StaticHost.Name">baiud.com</stringProp>
<stringProp name="StaticHost.Address">172.16.10.187</stringProp>
</elementProp>
</collectionProp>
<boolProp name="DNSCacheManager.clearEachIteration">true</boolProp>
<boolProp name="DNSCacheManager.isCustomResolver">true</boolProp>
</DNSCacheManager>
*/
Document document = ele.getOwnerDocument();
Element element = document.createElement(DNS_CACHE_MANAGER);
element.setAttribute("guiclass", "DNSCachePanel");
element.setAttribute("testclass", "DNSCacheManager");
element.setAttribute("testname", "DNS Cache Manager");
element.setAttribute("enabled", "true");
Element collectionProp = document.createElement(COLLECTION_PROP);
collectionProp.setAttribute("name", "DNSCacheManager.servers");
element.appendChild(collectionProp);
Element collectionProp2 = document.createElement(COLLECTION_PROP);
collectionProp2.setAttribute("name", "DNSCacheManager.hosts");
element.appendChild(collectionProp2);
element.appendChild(createBoolProp(document, "DNSCacheManager.clearEachIteration", true));
element.appendChild(createBoolProp(document, "DNSCacheManager.isCustomResolver", true));
hashTree.appendChild(element);
// 空的 hashTree
hashTree.appendChild(document.createElement(HASH_TREE_ELEMENT));
}
private void processCheckoutConfigTestElement(Element ele) {
if (context.getProperty("timeout") == null || StringUtils.isBlank(context.getProperty("timeout").toString())) {
return;
@ -607,43 +549,6 @@ public class JmeterDocumentParser implements DocumentParser {
}
private void processDnsCacheManager(Element ele) {
Object domains = context.getProperty("domains");
if (!(domains instanceof List)) {
return;
}
if (((List) domains).size() == 0) {
return;
}
NodeList childNodes = ele.getChildNodes();
for (int i = 0, size = childNodes.getLength(); i < size; i++) {
Node item = childNodes.item(i);
if (item instanceof Element && nodeNameEquals(item, "collectionProp")
&& org.apache.commons.lang3.StringUtils.equals(((Element) item).getAttribute("name"), "DNSCacheManager.hosts")) {
Document document = item.getOwnerDocument();
for (Object d : (List) domains) {
JSONObject jsonObject = JSON.parseObject(d.toString());
if (!jsonObject.getBooleanValue("enable")) {
continue;
}
Element elementProp = document.createElement("elementProp");
elementProp.setAttribute("name", jsonObject.getString("domain"));
elementProp.setAttribute("elementType", "StaticHost");
elementProp.appendChild(createStringProp(document, "StaticHost.Name", jsonObject.getString("domain")));
elementProp.appendChild(createStringProp(document, "StaticHost.Address", jsonObject.getString("ip")));
item.appendChild(elementProp);
}
}
if (item instanceof Element && nodeNameEquals(item, BOOL_PROP)
&& org.apache.commons.lang3.StringUtils.equals(((Element) item).getAttribute("name"), "DNSCacheManager.isCustomResolver")) {
item.getFirstChild().setNodeValue("true");
}
}
}
private void processConfigTestElement(Element ele) {
NodeList childNodes = ele.getChildNodes();

View File

@ -9,8 +9,8 @@
</el-form-item>
<el-form-item>
<el-input-number
:disabled="readOnly" size="mini" v-model="timeout"
:min="0"/>
:disabled="readOnly" size="mini" v-model="timeout"
:min="0"/>
</el-form-item>
<el-form-item>
ms
@ -24,8 +24,8 @@
</el-form-item>
<el-form-item>
<el-input-number
:disabled="readOnly" size="mini" :min="0"
v-model="responseTimeout"/>
:disabled="readOnly" size="mini" :min="0"
v-model="responseTimeout"/>
</el-form-item>
<el-form-item>
ms
@ -38,9 +38,9 @@
<div>
{{ $t('load_test.granularity') }}
<el-popover
placement="left"
width="300"
trigger="hover">
placement="left"
width="300"
trigger="hover">
<el-table :data="granularityData">
<el-table-column property="start" :label="$t('load_test.duration')">
<template v-slot:default="scope">
@ -69,13 +69,86 @@
</el-form-item>
<el-form-item>
<el-input
:disabled="readOnly" size="mini" v-model="statusCodeStr"
:placeholder="$t('load_test.separated_by_commas')"
@input="checkStatusCode"></el-input>
:disabled="readOnly" size="mini" v-model="statusCodeStr"
:placeholder="$t('load_test.separated_by_commas')"
@input="checkStatusCode"></el-input>
</el-form-item>
</el-form>
</el-col>
</el-row>
<!-- DNS -->
<el-row type="flex" justify="start">
<el-col :span="8">
<h3>{{ $t('load_test.domain_bind') }}</h3>
<el-button :disabled="readOnly" icon="el-icon-circle-plus-outline" plain size="mini" @click="add('domains')">
{{ $t('commons.add') }}
</el-button>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-table :data="domains" size="mini" class="tb-edit" align="center" border highlight-current-row>
<el-table-column
align="center"
:label="$t('load_test.domain')"
show-overflow-tooltip>
<template v-slot:default="{row}">
<el-input
size="mini"
v-if="!readOnly"
type="textarea"
:rows="1"
class="edit-input"
v-model="row.domain"
:placeholder="$t('load_test.domain')"
clearable>
</el-input>
<span>{{ row.domain }}</span>
</template>
</el-table-column>
<el-table-column
align="center"
:label="$t('load_test.ip')"
show-overflow-tooltip>
<template v-slot:default="{row}">
<el-input
size="mini"
v-if="!readOnly"
type="textarea"
class="edit-input"
:rows="1"
v-model="row.ip"
:placeholder="$t('load_test.ip')"
clearable></el-input>
<span>{{ row.ip }}</span>
</template>
</el-table-column>
<el-table-column
align="center"
:label="$t('load_test.enable')"
show-overflow-tooltip>
<template v-slot:default="{row}">
<el-switch
:disabled="!row.edit || readOnly"
size="mini"
v-model="row.enable"
inactive-color="#DCDFE6"
>
</el-switch>
</template>
</el-table-column>
<el-table-column align="center" :label="$t('load_test.operating')">
<template v-slot:default="{row, $index}">
<ms-table-operator-button :disabled="readOnly" :tip="$t('commons.delete')" icon="el-icon-delete"
type="danger"
@exec="del(row, 'domains', $index)"/>
</template>
</el-table-column>
</el-table>
</el-col>
</el-row>
<!-- csv 配置 -->
<el-row>
<el-col :span="8">
@ -86,9 +159,9 @@
<el-col :span="24">
<el-table :data="csvFiles" size="mini" class="tb-edit" align="center" border highlight-current-row>
<el-table-column
align="center"
prop="name"
:label="$t('commons.name')">
align="center"
prop="name"
:label="$t('commons.name')">
</el-table-column>
<el-table-column align="center" prop="csvSplit" :label="$t('load_test.csv_split')">
<template v-slot:default="{row}">
@ -117,56 +190,56 @@
<el-col :span="24">
<el-table :data="params" size="mini" class="tb-edit" align="center" border highlight-current-row>
<el-table-column
align="center"
:label="$t('load_test.param_name')"
show-overflow-tooltip>
align="center"
:label="$t('load_test.param_name')"
show-overflow-tooltip>
<template v-slot:default="{row}">
<el-input
size="mini"
v-if="!readOnly"
type="textarea"
:rows="1"
class="edit-input"
v-model="row.name"
:placeholder="$t('load_test.param_name')"
clearable>
size="mini"
v-if="!readOnly"
type="textarea"
:rows="1"
class="edit-input"
v-model="row.name"
:placeholder="$t('load_test.param_name')"
clearable>
</el-input>
<span>{{ row.name }}</span>
</template>
</el-table-column>
<el-table-column
align="center"
:label="$t('load_test.enable')"
show-overflow-tooltip>
<template v-slot:default="{row}">
<el-switch
:disabled="!row.edit || readOnly"
size="mini"
v-model="row.enable"
inactive-color="#DCDFE6">
</el-switch>
</template>
</el-table-column>
<el-table-column
:label="$t('load_test.param_value')"
show-overflow-tooltip align="center">
:label="$t('load_test.param_value')"
show-overflow-tooltip align="center">
<template v-slot:default="{row}">
<!-- <template v-if="row.edit">
<el-input v-model="row.value" class="edit-input" size="mini"/>
</template>
<span v-else>{{ row.value }}</span>-->
<el-input
size="mini"
v-if="!readOnly"
type="textarea"
class="edit-input"
:rows="1"
v-model="row.value"
:placeholder="$t('load_test.param_value')"
clearable></el-input>
size="mini"
v-if="!readOnly"
type="textarea"
class="edit-input"
:rows="1"
v-model="row.value"
:placeholder="$t('load_test.param_value')"
clearable></el-input>
<span>{{ row.value }}</span>
</template>
</el-table-column>
<el-table-column
align="center"
:label="$t('load_test.enable')"
show-overflow-tooltip>
<template v-slot:default="{row}">
<el-switch
:disabled="!row.edit || readOnly"
size="mini"
v-model="row.enable"
inactive-color="#DCDFE6">
</el-switch>
</template>
</el-table-column>
<el-table-column align="center" :label="$t('load_test.operating')">
<template v-slot:default="{row, $index}">
<ms-table-operator-button :disabled="readOnly" :tip="$t('commons.delete')" icon="el-icon-delete"
@ -191,56 +264,56 @@
<el-col :span="24">
<el-table :data="properties" size="mini" class="tb-edit" align="center" border highlight-current-row>
<el-table-column
align="center"
:label="$t('load_test.param_name')"
show-overflow-tooltip>
align="center"
:label="$t('load_test.param_name')"
show-overflow-tooltip>
<template v-slot:default="{row}">
<el-input
size="mini"
v-if="!readOnly"
type="textarea"
:rows="1"
class="edit-input"
v-model="row.name"
:placeholder="$t('load_test.param_name')"
clearable>
size="mini"
v-if="!readOnly"
type="textarea"
:rows="1"
class="edit-input"
v-model="row.name"
:placeholder="$t('load_test.param_name')"
clearable>
</el-input>
<span>{{ row.name }}</span>
</template>
</el-table-column>
<el-table-column
align="center"
:label="$t('load_test.enable')"
show-overflow-tooltip>
<template v-slot:default="{row}">
<el-switch
:disabled="!row.edit || readOnly"
size="mini"
v-model="row.enable"
inactive-color="#DCDFE6">
</el-switch>
</template>
</el-table-column>
<el-table-column
:label="$t('load_test.param_value')"
show-overflow-tooltip align="center">
:label="$t('load_test.param_value')"
show-overflow-tooltip align="center">
<template v-slot:default="{row}">
<!-- <template v-if="row.edit">
<el-input v-model="row.value" class="edit-input" size="mini"/>
</template>
<span v-else>{{ row.value }}</span>-->
<el-input
size="mini"
v-if="!readOnly"
type="textarea"
class="edit-input"
:rows="1"
v-model="row.value"
:placeholder="$t('load_test.param_value')"
clearable></el-input>
size="mini"
v-if="!readOnly"
type="textarea"
class="edit-input"
:rows="1"
v-model="row.value"
:placeholder="$t('load_test.param_value')"
clearable></el-input>
<span>{{ row.value }}</span>
</template>
</el-table-column>
<el-table-column
align="center"
:label="$t('load_test.enable')"
show-overflow-tooltip>
<template v-slot:default="{row}">
<el-switch
:disabled="!row.edit || readOnly"
size="mini"
v-model="row.enable"
inactive-color="#DCDFE6">
</el-switch>
</template>
</el-table-column>
<el-table-column align="center" :label="$t('load_test.operating')">
<template v-slot:default="{row, $index}">
<ms-table-operator-button :disabled="readOnly" :tip="$t('commons.delete')" icon="el-icon-delete"
@ -269,9 +342,9 @@
<el-col :span="24">
<el-table :data="monitorParams" size="mini" class="tb-edit" border highlight-current-row>
<el-table-column
align="center"
prop="name"
:label="$t('commons.name')">
align="center"
prop="name"
:label="$t('commons.name')">
</el-table-column>
<!-- <el-table-column-->
<!-- align="center"-->
@ -288,19 +361,19 @@
<!-- prop="monitorStatus"-->
<!-- label="监控状态">-->
<el-table-column
align="center"
prop="ip"
label="IP">
align="center"
prop="ip"
label="IP">
</el-table-column>
<el-table-column
align="center"
prop="port"
label="Port">
align="center"
prop="port"
label="Port">
</el-table-column>
<el-table-column
align="center"
prop="description"
:label="$t('commons.description')">
align="center"
prop="description"
:label="$t('commons.description')">
</el-table-column>
<el-table-column align="center" :label="$t('load_test.operating')">
<template v-slot:default="{row, $index}">