Skip to content

Commit 996190b

Browse files
authored
add function to find peak of load (#37)
* add function to find peak of load
1 parent 4135338 commit 996190b

39 files changed

+631
-144
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
monitoring:
2+
url: "http://your_url"
3+
metrics:
4+
- cpu_usage: # internal name of metric
5+
tag: "system_cpu_usage" # tag to query metric
6+
max: 0.9 # [optional] max boundary value
7+
- jvm_memory_used_bytes: # internal name of metric
8+
contains_tag: "jvm_memory_used_bytes" # get sum value of metrics, that contains this tag
9+
max: 256_000_000.0 # [optional] max boundary value

configs/repo/components/core/openshift/loadtest-simple-example/loadtest-simple-example-requests/get.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
plan.get.requests:
22
- hello-request:
3-
component: helloworld-springboot #Name of component or 'domain: target system domain'
3+
component: helloworld #Name of component or 'domain: target system domain'
44
method: GET
55
path: /hello
66
protocol: http
@@ -10,7 +10,7 @@ plan.get.requests:
1010
- paramName: test-param-value
1111
- nextParamName: next-test-param-value
1212
- next-hello-request:
13-
component: helloworld-springboot
13+
component: helloworld
1414
method: GET
1515
path: /next-hello
1616
protocol: http

configs/repo/components/core/openshift/loadtest-simple-example/loadtest-simple-example-requests/post.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
plan.post.requests:
22
- post-request:
3-
component: helloworld-springboot
3+
component: helloworld
44
method: POST
55
path: /post-hello
66
protocol: http
@@ -12,7 +12,7 @@ plan.post.requests:
1212
"nextData": "nextData"
1313
}'
1414
- post-request-header:
15-
component: helloworld-springboot
15+
component: helloworld
1616
method: POST
1717
path: /post-hello-header
1818
protocol: http

configs/repo/components/core/openshift/loadtest-simple-example/loadtest-simple-example-requests/put.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
plan.put.requests:
22
- put-request:
3-
component: helloworld-springboot
3+
component: helloworld
44
method: PUT
55
path: /put-hello
66
headers:
@@ -12,7 +12,7 @@ plan.put.requests:
1212
"nextData": "nextData"
1313
}'
1414
- delete-request:
15-
component: helloworld-springboot
15+
component: helloworld
1616
method: DELETE
1717
path: /delete-hello
1818
protocol: http
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
#include loadtest-simple-example-requests
2+
#include metrics
23

3-
numberOfThreads: 10
4+
numberOfThreads: 250 #users on one slave node
45
rampUpPeriod: 1
5-
duration: 20
6+
duration: 500
7+
8+
peak-load-test:
9+
step: 25 #users on one slave node
10+
errors: 60 #percent of errors
11+
average-response-time: 1500 #value in mc

configs/repo/components/osdf/osdf-core/includes/osdf-loadtest/deploy.deploy

+2
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@
1919

2020
image-master.url: ${[email protected]}/jmeter-master:latest
2121
image-slave.url: ${[email protected]}/jmeter-slave:latest
22+
pull-secret-name: pull-secret-name
2223

2324
master.port: 60000
2425
slave.port: 50000
2526
slave.second-port: 1099
2627

28+
limits.memory: 1024M
2729
istioInject: false
2830
replicas.count: 1

configs/repo/components/osdf/osdf-core/includes/osdf-loadtest/master-templates/deployment.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ spec:
1414
annotations:
1515
sidecar.istio.io/inject: '${this@istioInject}'
1616
spec:
17+
imagePullSecrets:
18+
- name: ${this@pull-secret-name}
1719
containers:
1820
- image: ${[email protected]}
1921
volumeMounts:

configs/repo/components/osdf/osdf-core/includes/osdf-loadtest/slave-templates/deployment.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ spec:
1414
annotations:
1515
sidecar.istio.io/inject: '${this@istioInject}'
1616
spec:
17+
imagePullSecrets:
18+
- name: ${this@pull-secret-name}
1719
containers:
1820
- image: ${[email protected]}
1921
imagePullPolicy: Always

configs/repo/components/osdf/osdf-core/settings/osdf-pod-deployment/settings.deploy

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#var unfiltered.java.opts: ${process::[email protected]:}
2-
java.opts: #{'${[email protected]}'.replace('${process::[email protected]}', '')}
2+
java.opts: #{'${[email protected]}'.replace('${process::[email protected]:}', '')}
33

44
timezone: ${this@timezone:UTC}
55

Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
cluster.url.base: unknown
2-
cluster.url.api: unknown
3-
project: unknown
4-
registry.project.url: unknown
1+
cluster.url.base:
2+
cluster.url.api:
3+
project:
4+
registry.project.url:

configs/repo/envs/base.yaml

+10-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
helloworld:
22
components:
3-
- helloworld-springboot
3+
- helloworld
44

55
kubernetes:
66
components:
@@ -10,12 +10,16 @@ helloworld-istio:
1010
components:
1111
- helloworld-springboot-istio
1212

13-
demo:
14-
components:
15-
- demo-backend
16-
- demo-frontend
17-
- chaos
13+
#demo:
14+
# components:
15+
# - demo-backend
16+
# - demo-frontend
17+
# - chaos
1818

1919
jmeter:
2020
components:
2121
- loadtest-simple-example
22+
23+
metrics:
24+
components:
25+
- metrics

jmeter.gradle

+9-13
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,19 @@
11
dependencies {
2-
compile('oro:oro:2.0.8')
3-
compile "com.thoughtworks.xstream:xstream:1.4.7"
4-
compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.10'
5-
compile('org.apache.jmeter:ApacheJMeter_core:5.1.1') {
2+
implementation 'oro:oro:2.0.8'
3+
implementation 'com.thoughtworks.xstream:xstream:1.4.12'
4+
implementation 'org.apache.commons:commons-lang3:3.10'
5+
implementation ('org.apache.jmeter:ApacheJMeter_core:5.1.1') {
66
transitive = false
77
}
8-
compile('org.apache.jmeter:ApacheJMeter_components:5.1.1') {
8+
implementation('org.apache.jmeter:ApacheJMeter_components:5.1.1') {
99
transitive = false
1010
}
11-
compile('org.apache.jmeter:ApacheJMeter_http:5.1.1') {
11+
implementation('org.apache.jmeter:ApacheJMeter_http:5.1.1') {
1212
transitive = false
1313
}
14-
compile('org.apache.jmeter:jorphan:5.1.1') {
15-
transitive = false
16-
}
17-
compile('org.slf4j:slf4j-api:1.7.25') {
18-
transitive = false
19-
}
20-
compile('org.slf4j:slf4j-simple:1.7.25') {
14+
implementation('org.apache.jmeter:jorphan:5.1.1') {
2115
transitive = false
2216
}
17+
implementation('org.slf4j:slf4j-api:1.7.25')
18+
implementation('org.slf4j:slf4j-simple:1.7.25')
2319
}

src/main/java/io/microconfig/osdf/api/declarations/LoadTestingApi.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@
1414
public interface LoadTestingApi {
1515
@ApiCommand(description = "Run load testing", order = 1)
1616
void loadTest(@ConsoleParam(value = JmeterPlanPathParameter.class, type = OPTIONAL) Path jmeterPlanPath,
17-
@ConsoleParam(value = JmeterComponentNameParameter.class, type = REQUIRED) String configName,
17+
@ConsoleParam(value = JmeterComponentNameParameter.class, type = REQUIRED) String componentName,
1818
@ConsoleParam(value = JmeterSlavesNumberParameter.class, type = OPTIONAL) Integer numberOfSlaves);
1919

20+
@ApiCommand(description = "Find peak load", order = 2)
21+
void findPeakLoad(@ConsoleParam(value = JmeterComponentNameParameter.class, type = REQUIRED) String componentName,
22+
@ConsoleParam(value = JmeterSlavesNumberParameter.class, type = OPTIONAL) Integer numberOfSlaves);
2023
}

src/main/java/io/microconfig/osdf/api/implementations/LoadTestingApiImpl.java

+13-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.nio.file.Path;
1010

1111
import static io.microconfig.osdf.commands.LoadTestCommand.loadTestCommand;
12+
import static io.microconfig.osdf.commands.FindPeakLoadCommand.findPeakLoadCommand;
1213
import static io.microconfig.osdf.loadtesting.jmeter.JmeterPlanPathGenerator.jmeterPlanPathGenerator;
1314
import static io.microconfig.osdf.loadtesting.jmeter.configs.JmeterConfigProcessor.configProcessor;
1415
import static io.microconfig.osdf.loadtesting.jmeter.loader.JmeterPathLoader.pathLoader;
@@ -27,8 +28,18 @@ public void loadTest(Path jmeterPlanPath, String componentName, Integer numberOf
2728
int number = numberOfSlaves != null ? numberOfSlaves : 3;
2829
Path path = pathLoader(paths, componentName).jmeterComponentsPathLoad();
2930
JmeterConfigProcessor configProcessor = jmeterPlanPath != null ?
30-
configProcessor(path, number, jmeterPlanPath, true) :
31-
configProcessor(path, number, jmeterPlanPathGenerator(paths, cli, componentName).generate(), false);
31+
configProcessor(path, number, jmeterPlanPath) :
32+
configProcessor(path, number, jmeterPlanPathGenerator(paths, cli, componentName).generate());
33+
configProcessor.init();
3234
loadTestCommand(cli, configProcessor).run();
3335
}
36+
37+
@Override
38+
public void findPeakLoad(String componentName, Integer numberOfSlaves) {
39+
int number = numberOfSlaves != null ? numberOfSlaves : 3;
40+
Path path = pathLoader(paths, componentName).jmeterComponentsPathLoad();
41+
JmeterConfigProcessor configProcessor =
42+
configProcessor(path, number, jmeterPlanPathGenerator(paths, cli, componentName).generate());
43+
findPeakLoadCommand(cli, configProcessor).run();
44+
}
3445
}

src/main/java/io/microconfig/osdf/api/parameter/JmeterSlavesNumberParameter.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
import io.microconfig.osdf.parameters.ArgParameter;
44

5+
import static java.lang.Integer.valueOf;
6+
57
public class JmeterSlavesNumberParameter extends ArgParameter<Integer> {
68
public JmeterSlavesNumberParameter() {
79
super("slavesNumber", "n", "Number of slaves nodes");
810
}
911

1012
@Override
1113
public Integer get() {
12-
return getValue() != null ? Integer.valueOf(getValue()) : null;
14+
return getValue() != null ? valueOf(getValue()) : null;
1315
}
1416
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package io.microconfig.osdf.commands;
2+
3+
import io.microconfig.osdf.cluster.cli.ClusterCLI;
4+
import io.microconfig.osdf.cluster.pod.Pod;
5+
import io.microconfig.osdf.loadtesting.jmeter.JmeterComponent;
6+
import io.microconfig.osdf.loadtesting.jmeter.JmeterResourcesCleaner;
7+
import io.microconfig.osdf.loadtesting.jmeter.configs.JmeterConfigProcessor;
8+
import io.microconfig.osdf.loadtesting.jmeter.configs.JmeterMasterConfig;
9+
import io.microconfig.osdf.loadtesting.jmeter.loader.JmeterComponentsLoader;
10+
import io.microconfig.osdf.loadtesting.jmeter.metrics.PeakMetrics;
11+
import io.microconfig.osdf.loadtesting.jmeter.results.PeakResultsBuilder;
12+
import lombok.RequiredArgsConstructor;
13+
14+
import java.util.List;
15+
16+
import static io.microconfig.osdf.loadtesting.jmeter.JmeterDeployUtils.deployDeployments;
17+
import static io.microconfig.osdf.loadtesting.jmeter.JmeterDeployUtils.setSlavesHosts;
18+
import static io.microconfig.osdf.loadtesting.jmeter.JmeterResourcesCleaner.jmeterResourcesCleaner;
19+
import static io.microconfig.osdf.loadtesting.jmeter.loader.JmeterComponentsLoader.jmeterComponentsLoader;
20+
import static io.microconfig.osdf.loadtesting.jmeter.metrics.PeakMetrics.peakMetrics;
21+
import static io.microconfig.osdf.loadtesting.jmeter.metrics.PeakMetricsParser.peakMetricsParser;
22+
import static io.microconfig.osdf.loadtesting.jmeter.metrics.loader.JmeterMetricsPuller.jmeterMetricsPuller;
23+
import static io.microconfig.osdf.loadtesting.jmeter.results.PeakResultsBuilder.peakResultsBuilder;
24+
import static io.microconfig.utils.Logger.announce;
25+
26+
@RequiredArgsConstructor
27+
public class FindPeakLoadCommand {
28+
private final ClusterCLI cli;
29+
private final JmeterConfigProcessor configProcessor;
30+
31+
public static FindPeakLoadCommand findPeakLoadCommand(ClusterCLI cli, JmeterConfigProcessor jmeterConfigProcessor) {
32+
return new FindPeakLoadCommand(cli, jmeterConfigProcessor);
33+
}
34+
35+
public void run() {
36+
configProcessor.init();
37+
announce("Load components");
38+
JmeterComponentsLoader jmeterLoader = jmeterComponentsLoader(cli, configProcessor);
39+
List<JmeterComponent> slaveComponents = jmeterLoader.loadSlaves();
40+
JmeterComponent masterComponent = jmeterLoader.loadMaster();
41+
try (JmeterResourcesCleaner ignore = jmeterResourcesCleaner(jmeterLoader)) {
42+
deployDeployments(slaveComponents);
43+
setSlavesHosts(configProcessor, slaveComponents);
44+
findPeak(masterComponent, slaveComponents);
45+
}
46+
}
47+
48+
private void findPeak(JmeterComponent masterComponent, List<JmeterComponent> slaveComponents) {
49+
PeakMetrics userLimits = peakMetricsParser(configProcessor.loadUserConfig()).parse();
50+
PeakMetrics currentMetrics = peakMetrics(userLimits.getMetricsFromConfig());
51+
int slaveNodesNumber = configProcessor.getSlaveConfigs().size();
52+
while (!userLimits.checkPeakResults(currentMetrics)) {
53+
currentMetrics.setStep(currentMetrics.getStep() + userLimits.getStep());
54+
announce("Check load. Number of users: " + currentMetrics.getStep() * slaveNodesNumber);
55+
redefineMasterAndDeploy(masterComponent, currentMetrics, slaveNodesNumber);
56+
jmeterMetricsPuller(configProcessor).load(currentMetrics, masterComponent);
57+
showResult(currentMetrics, currentMetrics);
58+
deleteResources(masterComponent, slaveComponents);
59+
}
60+
announce("The peak load between " + (currentMetrics.getStep() - userLimits.getStep()) * slaveNodesNumber
61+
+ "-" + currentMetrics.getStep() * slaveNodesNumber + " users");
62+
}
63+
64+
private void showResult(PeakMetrics userLimits, PeakMetrics currentMetrics) {
65+
PeakResultsBuilder builder = peakResultsBuilder(userLimits.getMetricsFromConfig(), currentMetrics);
66+
announce(builder.build());
67+
}
68+
69+
private void redefineMasterAndDeploy(JmeterComponent masterComponent, PeakMetrics currentMetrics, int slaveNodesNumber) {
70+
JmeterMasterConfig masterConfig = configProcessor.getMasterConfig();
71+
masterConfig.setThreadGroupAttribute("ThreadGroup.num_threads", currentMetrics.getStep());
72+
masterConfig.setThreadGroupAttribute("ThreadGroup.duration", currentMetrics.getStep() * slaveNodesNumber);
73+
masterConfig.setJmeterPlanInMasterTemplateConfig();
74+
deployDeployments(masterComponent);
75+
}
76+
77+
private void deleteResources(JmeterComponent masterComponent, List<JmeterComponent> slaveComponents) {
78+
masterComponent.deleteAll();
79+
slaveComponents.forEach(component -> component.pods().forEach(Pod::delete));
80+
}
81+
}
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
package io.microconfig.osdf.commands;
22

33
import io.microconfig.osdf.cluster.cli.ClusterCLI;
4-
import io.microconfig.osdf.cluster.pod.Pod;
54
import io.microconfig.osdf.loadtesting.jmeter.JmeterComponent;
6-
import io.microconfig.osdf.loadtesting.jmeter.JmeterLogResult;
75
import io.microconfig.osdf.loadtesting.jmeter.JmeterResourcesCleaner;
86
import io.microconfig.osdf.loadtesting.jmeter.configs.JmeterConfigProcessor;
97
import io.microconfig.osdf.loadtesting.jmeter.loader.JmeterComponentsLoader;
108
import lombok.RequiredArgsConstructor;
119

12-
import java.util.ArrayList;
1310
import java.util.List;
1411

15-
import static io.microconfig.osdf.loadtesting.jmeter.JmeterLogResult.jmeterLogResult;
12+
import static io.microconfig.osdf.loadtesting.jmeter.JmeterDeployUtils.*;
1613
import static io.microconfig.osdf.loadtesting.jmeter.JmeterResourcesCleaner.jmeterResourcesCleaner;
1714
import static io.microconfig.osdf.loadtesting.jmeter.loader.JmeterComponentsLoader.jmeterComponentsLoader;
1815
import static io.microconfig.utils.Logger.announce;
@@ -27,42 +24,16 @@ public static LoadTestCommand loadTestCommand(ClusterCLI cli, JmeterConfigProces
2724
}
2825

2926
public void run() {
30-
jmeterConfigProcessor.init();
3127
announce("Load components");
3228
JmeterComponentsLoader jmeterLoader = jmeterComponentsLoader(cli, jmeterConfigProcessor);
3329
List<JmeterComponent> slaveComponents = jmeterLoader.loadSlaves();
3430
JmeterComponent masterComponent = jmeterLoader.loadMaster();
3531

36-
try (JmeterResourcesCleaner ignore = jmeterResourcesCleaner(jmeterLoader,
37-
jmeterConfigProcessor.getJmeterComponentsPath())) {
32+
try (JmeterResourcesCleaner ignore = jmeterResourcesCleaner(jmeterLoader)) {
3833
deployDeployments(slaveComponents);
3934
setSlavesHosts(jmeterConfigProcessor, slaveComponents);
40-
deployDeployments(List.of(masterComponent));
41-
waitResults(jmeterConfigProcessor, masterComponent);
35+
deployDeployments(masterComponent);
36+
announce(waitResults(jmeterConfigProcessor, masterComponent));
4237
}
4338
}
44-
45-
private void setSlavesHosts(JmeterConfigProcessor jmeterConfigProcessor, List<JmeterComponent> slaveComponents) {
46-
List<String> slaveHosts = new ArrayList<>();
47-
slaveComponents.forEach(component -> slaveHosts.add(component.getServiceIp()));
48-
jmeterConfigProcessor.getMasterConfig().setHostsInMasterTemplateConfig(slaveHosts);
49-
}
50-
51-
private void deployDeployments(List<JmeterComponent> components) {
52-
components.forEach(component -> {
53-
announce("Deploy " + component.getComponentName());
54-
component.deploy();
55-
});
56-
}
57-
58-
private void waitResults(JmeterConfigProcessor jmeterConfigProcessor, JmeterComponent masterComponent) {
59-
int duration = jmeterConfigProcessor.getMasterConfig().getDuration(jmeterConfigProcessor.isJmxConfig());
60-
announce("Start load testing. Duration: " + duration + " sec");
61-
JmeterLogResult jmeterChecker = jmeterLogResult(duration * 2, "... end of run", "summary");
62-
Pod pod = masterComponent.pods()
63-
.stream()
64-
.findFirst()
65-
.orElseThrow();
66-
announce(jmeterChecker.getResults(pod));
67-
}
6839
}

0 commit comments

Comments
 (0)