K6 is an open-source load-testing tool that allows developers and DevOps engineers to measure the performance and scalability of web applications and APIs.
It is written in Go and allows for both scripting and execution of load tests, making it easy for developers to create and run tests without the need for specialized knowledge.
Installing K6
By default, your package repository on Ubuntu won’t know where to download k6 from, so you first need to set that up.
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 379CE192D401AB61
echo "deb https://dl.bintray.com/loadimpact/deb stable main" | sudo tee -a /etc/apt/sources.list
With that in place, you can install k6 with apt-get (after doing an update first).
sudo apt-get update
sudo apt-get install k6
One of the key features of k6 is its ability to generate realistic and customizable loads. This is achieved through the use of virtual users, or VUs, which simulate the behavior of actual users visiting your website or web application.
These VUs can be configured to perform different actions, such as visiting pages, submitting forms, and making API calls, allowing you to test different parts of your application.
K6 also includes a built-in test runner that allows you to configure and execute load tests from the command line.
You can set various parameters, such as the number of VUs, the duration of the test, and the rate of requests, making it easy to test your application under different loads.
Another advantage of k6 is that it supports multiple protocols, including HTTP, WebSockets, and gRPC, making it a versatile tool that can be used to test a wide variety of applications.
Additionally, k6 provides a rich set of metrics and analytics, including response times, throughput, and error rates, which can be used to identify bottlenecks and optimize performance.
Let’s make a very basic k6 Javascript test. Create a file called script.js with the following content.
import http from 'k6/http';
import { sleep } from 'k6';
export default function() {
http.get('http://127.0.0.1/');
sleep(1);
}
Replace the IP address on line 5 with the domain or URL that you want to test.
Execute the script with the k6 command.
k6 run script.js
This will make one request to the URL.
The output of this will be like this:
/\ |‾‾| /‾‾/ /‾‾/
/\ / \ | |/ / / /
/ \/ \ | ( / ‾‾\
/ \ | |\ \ | (‾) |
/ __________ \ |__| \__\ \_____/ .io
execution: local
script: scriptttt.js
output: -
scenarios: (100.00%) 1 scenario, 1 max VUs, 10m30s max duration (incl. graceful stop):
* default: 1 iterations for each of 1 VUs (maxDuration: 10m0s, gracefulStop: 30s)
running (00m01.1s), 0/1 VUs, 1 complete and 0 interrupted iterations
default ✓ [========================] 1 VUs 00m01.1s/10m0s 1/1 iters, 1 per VU
data_received..................: 52 kB 49 kB/s
data_sent......................: 78 B 73 B/s
http_req_blocked...............: avg=387.52µs min=387.52µs med=387.52µs max=387.52µs p(90)=387.52µs p(95)=387.52µs
http_req_connecting............: avg=315.43µs min=315.43µs med=315.43µs max=315.43µs p(90)=315.43µs p(95)=315.43µs
http_req_duration..............: avg=70.17ms min=70.17ms med=70.17ms max=70.17ms p(90)=70.17ms p(95)=70.17ms
{ expected_response:true }...: avg=70.17ms min=70.17ms med=70.17ms max=70.17ms p(90)=70.17ms p(95)=70.17ms
http_req_failed................: 0.00% ✓ 0 ✗ 1
http_req_receiving.............: avg=8.43ms min=8.43ms med=8.43ms max=8.43ms p(90)=8.43ms p(95)=8.43ms
http_req_sending...............: avg=62.08µs min=62.08µs med=62.08µs max=62.08µs p(90)=62.08µs p(95)=62.08µs
http_req_tls_handshaking.......: avg=0s min=0s med=0s max=0s p(90)=0s p(95)=0s
http_req_waiting...............: avg=61.67ms min=61.67ms med=61.67ms max=61.67ms p(90)=61.67ms p(95)=61.67ms
http_reqs......................: 1 0.932894/s
iteration_duration.............: avg=1.07s min=1.07s med=1.07s max=1.07s p(90)=1.07s p(95)=1.07s
iterations.....................: 1 0.932894/s
vus............................: 1 min=1 max=1
vus_max........................: 1 min=1 max=1
In order to consistently make 10 concurrent requests over the course of 30 seconds, you can pass in the –vus (virtual users) and –duration arguments as follows.
k6 run --vus 10 --duration 30s script.js
In order to simulate a gradual increase in traffic, we can define options in our Javascript file with multiple stages.
import http from 'k6/http';
import { check, sleep } from 'k6';
export let options = {
stages: [
{ duration: '15s', target: 100 },
{ duration: '30s', target: 100 },
{ duration: '15s', target: 0 },
],
};
export default function() {
let res = http.get('http://192.168.1.14/');
check(res, { 'status was 200': r => r.status == 200 });
sleep(1);
}
Run the script using this command:
k6 run script.js
The output will be:
/\ |‾‾| /‾‾/ /‾‾/
/\ / \ | |/ / / /
/ \/ \ | ( / ‾‾\
/ \ | |\ \ | (‾) |
/ __________ \ |__| \__\ \_____/ .io
execution: local
script: script.js
output: -
scenarios: (100.00%) 1 scenario, 100 max VUs, 1m30s max duration (incl. graceful stop):
* default: Up to 100 looping VUs for 1m0s over 3 stages (gracefulRampDown: 30s, gracefulStop: 30s)
running (1m00.2s), 000/100 VUs, 941 complete and 0 interrupted iterations
default ✓ [======================================] 000/100 VUs 1m0s
✓ status was 200
checks.........................: 100.00% ✓ 941 ✗ 0
data_received..................: 49 MB 814 kB/s
data_sent......................: 74 kB 1.2 kB/s
http_req_blocked...............: avg=48.32µs min=3.01µs med=5.02µs max=1.84ms p(90)=301.52µs p(95)=335.73µs
http_req_connecting............: avg=34.81µs min=0s med=0s max=1.74ms p(90)=235.96µs p(95)=266.14µs
http_req_duration..............: avg=4.02s min=59.2ms med=4.87s max=5.37s p(90)=5.19s p(95)=5.22s
{ expected_response:true }...: avg=4.02s min=59.2ms med=4.87s max=5.37s p(90)=5.19s p(95)=5.22s
http_req_failed................: 0.00% ✓ 0 ✗ 941
http_req_receiving.............: avg=50.64ms min=2.91ms med=52.25ms max=158.88ms p(90)=77.93ms p(95)=85.66ms
http_req_sending...............: avg=154.12µs min=11.22µs med=19.98µs max=122.15ms p(90)=43.88µs p(95)=54.66µs
http_req_tls_handshaking.......: avg=0s min=0s med=0s max=0s p(90)=0s p(95)=0s
http_req_waiting...............: avg=3.97s min=53.21ms med=4.82s max=5.31s p(90)=5.13s p(95)=5.17s
http_reqs......................: 941 15.618949/s
iteration_duration.............: avg=5.02s min=1.06s med=5.87s max=6.37s p(90)=6.19s p(95)=6.22s
iterations.....................: 941 15.618949/s
vus............................: 8 min=7 max=100
vus_max........................: 100 min=100 max=100
In summary, k6 is a powerful and versatile load-testing tool that allows developers and DevOps engineers to measure the performance and scalability of web applications and APIs. Its customizable virtual user generation, support for multiple protocols, and rich set of metrics make it a useful tool for optimizing the performance of your application.