Skip to content

Commit 9feea7d

Browse files
authored
Merge pull request #13831 from guardian/ravi/k6-updates
Update k6 load testing utility and add README
2 parents 9ae472b + e60228b commit 9feea7d

File tree

3 files changed

+104
-4
lines changed

3 files changed

+104
-4
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Load Testing with k6
2+
3+
[Grafana k6](https://k6.io/) is a tool that will run a load test scenario against an endpoint and once complete provide detailed stats on latency and throughput metrics.
4+
5+
## Installing
6+
7+
From the k6 directory run
8+
9+
```
10+
./k6-install.sh
11+
```
12+
13+
Once finished you will see an example of how to run the script.
14+
15+
## Script
16+
17+
From the k6 directory run (for example with v0.58.0)
18+
19+
```
20+
./k6-v0.58.0-macos-arm64/k6 run k6.mjs
21+
```
22+
23+
The current script `k6.mjs` loads a locally saved JSON payload which will then POST to the DCR `/Article` endpoint. Using a local payload file and the PROD POST endpoint mimics production and also removes the step of a network fetch of the JSON payload from Frontend from the test scenario.
24+
25+
You can of course configure this to be any payload and endpoint you wish.
26+
27+
## Testing Advice
28+
29+
Test against a PROD build and endpoints.
30+
31+
Run the script 2-3 times to warm the app and instance if working from a cold start.
32+
33+
k6 can consume lots of memory, so ideally you shouldn't run it on the same compute as the app you are load testing.
34+
35+
k6 has a large API so its worth reading the docs and in particular the [overview](https://grafana.com/docs/k6/latest/).
36+
37+
## Output
38+
39+
Once complete k6 will output statistics like the following.
40+
41+
`http_req_duration` are the main stats to consider.
42+
43+
`iteration_duration` includes the time for k6 to run the script.
44+
45+
```
46+
/\ Grafana /‾‾/
47+
/\ / \ |\ __ / /
48+
/ \/ \ | |/ / / ‾‾\
49+
/ \ | ( | (‾) |
50+
/ __________ \ |_|\_\ \_____/
51+
52+
execution: local
53+
script: k6.mjs
54+
output: -
55+
56+
scenarios: (100.00%) 1 scenario, 10 max VUs, 1m30s max duration (incl. graceful stop):
57+
* default: 10 looping VUs for 1m0s (gracefulStop: 30s)
58+
59+
60+
61+
█ TOTAL RESULTS
62+
63+
checks_total.......................: 3786 62.955288/s
64+
checks_succeeded...................: 100.00% 3786 out of 3786
65+
checks_failed......................: 0.00% 0 out of 3786
66+
67+
✓ is status 200
68+
69+
HTTP
70+
http_req_duration.......................................................: avg=155.45ms min=54.91ms med=128.6ms max=2.23s p(90)=250.46ms p(95)=262.3ms
71+
{ expected_response:true }............................................: avg=155.45ms min=54.91ms med=128.6ms max=2.23s p(90)=250.46ms p(95)=262.3ms
72+
http_req_failed.........................................................: 0.00% 0 out of 3786
73+
http_reqs...............................................................: 3786 62.955288/s
74+
75+
EXECUTION
76+
iteration_duration......................................................: avg=158.65ms min=57.77ms med=131.66ms max=2.24s p(90)=253.37ms p(95)=265.44ms
77+
iterations..............................................................: 3786 62.955288/s
78+
vus.....................................................................: 10 min=10 max=10
79+
vus_max.................................................................: 10 min=10 max=10
80+
81+
NETWORK
82+
data_received...........................................................: 1.1 GB 19 MB/s
83+
data_sent...............................................................: 251 MB 4.2 MB/s
84+
85+
86+
87+
88+
running (1m00.1s), 00/10 VUs, 3786 complete and 0 interrupted iterations
89+
default ✓ [======================================] 10 VUs 1m0s
90+
```
91+
92+
## Testing in CODE
93+
94+
If testing in CODE:
95+
96+
- run the script from a detached instance
97+
- k6 may get killed by the OOM killer if an instance runs out of memory. First stop the DCR process using `systemctl stop {app-name}` where app-name is `article-rendering`, `facia-rendering` etc to free up memory. If the process is repeatedly killed, run from a larger instance type with more memory or run with a smaller number of VUs.
98+
- change the script endpoint to the loadbalancer of the stack you are interested in

dotcom-rendering/scripts/perf/k6/k6-install.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/bin/bash
2-
VERSION=v0.47.0
2+
VERSION=v0.58.0
33

44
download () {
55
printf "Downloading $1 ...\n\n"
@@ -18,11 +18,11 @@ if [[ $OS == "Linux" ]]; then
1818
download $LINUX_FILE
1919
tar -xvf $LINUX_FILE
2020
rm $LINUX_FILE
21-
printf "\nto run a test:\n./k6-$VERSION-linux-arm64/k6 run k6.mjs\n"
21+
printf "\n\n *** To run a test *** \n./k6-$VERSION-linux-arm64/k6 run k6.mjs\n\n"
2222
elif [[ $OS == "Mac" ]]; then
2323
MAC_FILE=k6-$VERSION-macos-arm64.zip
2424
download $MAC_FILE
2525
unzip $MAC_FILE
2626
rm $MAC_FILE
27-
printf "\nto run a test:\n./k6-$VERSION-macos-arm64/k6 run k6.mjs\n"
27+
printf "\n\n *** To run a test ***\n./k6-$VERSION-macos-arm64/k6 run k6.mjs\n\n"
2828
fi

dotcom-rendering/scripts/perf/k6/k6.mjs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import { check } from 'k6';
22
import { SharedArray } from 'k6/data';
33
import http from 'k6/http';
44

5-
const PORT = 3030;
5+
// assume prod server
6+
const PORT = 9000;
67

78
/** @type {import('k6/data').SharedArray} */
89
const jsonPayload = new SharedArray('jsonPayload', function () {
@@ -14,6 +15,7 @@ const jsonPayload = new SharedArray('jsonPayload', function () {
1415
export const options = {
1516
vus: 10,
1617
duration: '60s',
18+
insecureSkipTLSVerify: true,
1719
};
1820

1921
// eslint-disable-next-line import/no-default-export -- k6 requires a default export

0 commit comments

Comments
 (0)