k6
k6 is the codename for the next generation of Load Impact's load generator.
It features a modern codebase built on Go and integrates ES6, the latest iteration of Javascript, as a scripting language.
The simplest possible load script would be something along these lines:
// The script API is provided as ES6 modules, no global namespace pollution.
// If you prefer the older style of doing things, you may also use require().
import http from "k6/http";
// Export your test code as a 'default' function.
export default function() {
// Make an HTTP request; this will yield a variety of metrics, eg. 'request_duration'.
http.get("http://test.loadimpact.com/");
}
To run it, simply do...
$ k6 run script.js
Welcome to k6 v0.4.2!
execution: local
output: -
script: script.js
↳ duration: 10s
↳ vus: 10, max: 10
web ui: http://127.0.0.1:6565/
done [==========================================================] 10s / 10s
http_req_blocked: avg=19.57µs, max=14.9ms, med=1.28µs, min=808ns, p90=2.27µs, p95=7.1µs
http_req_connecting: avg=3.25µs, max=7.57ms, med=0s, min=0s, p90=0s, p95=0s
http_req_duration: avg=5.26ms, max=31.48ms, med=4.3ms, min=2.25ms, p90=7.69ms, p95=12.84ms
http_req_looking_up: avg=9.12µs, max=7.3ms, med=0s, min=0s, p90=0s, p95=0s
http_req_receiving: avg=121.95µs, max=13.84ms, med=69.3µs, min=38.57µs, p90=113.79µs, p95=140.04µs
http_req_sending: avg=18.27µs, max=4.92ms, med=12.09µs, min=6.12µs, p90=22.15µs, p95=28µs
http_req_waiting: avg=5.1ms, max=30.39ms, med=4.18ms, min=2.17ms, p90=7.33ms, p95=12.22ms
http_reqs: 17538
runs: 17538
$
Scripting
k6 bundles a number of useful APIs that allows you to control flow of your scripts for both load and functional test execution, e.g.:
import http from "k6/http";
import { check } from "k6";
import { Trend } from "k6/metrics";
// define our threshold within a global options-structure
export let options = {
thresholds: {
request_duration: ["avg<100"],
}
};
// create our Trend metric
var myTrend = new Trend("request_duration");
// Export our test code as a 'default' function.
export default function() {
var r = http.get("https://httpbin.org");
// add response time to our Trend-metric
myTrend.add(r.timings.duration);
// assert for functional correctness
check(r, {
"status is 200": (r) => r.status === 200,
"body size 1234 bytes": (r) => r.body.length === 1234
});
};
The above code can be run both as a load test or as a functional test, and will:
- create a Trend metric named “request_duration” and referred to in the code using the variable name myTrend
- define a threshold for the Trend metric. This threshold says that the load test should fail if the average value of the Trend metric goes below 100. This means that if at any time during the load test, the currently computed average of all sample values added to myTrend is less than 100, then the whole load test will be marked as failed.
- create a default function that will be executed repeatedly by all VUs in the load test. This function makes an HTTP request and adds the HTTP duration (
response.timings.duration
) to the Trend metric, while also asserting for HTTP 200 response (response.status
) and expected size of HTTP body (response.body.length
).
For more information, see the Getting Started Guide and Metrics Management Reference
Installation
There are a couple of ways to set up k6:
The simplest way to get started is to use our Docker image
docker pull loadimpact/k6
docker run --rm --net=host -v $(pwd)/myscript.js:/myscript.js loadimpact/k6 run /myscript.js
It's recommended to run k6 with --net=host
as it slightly improves network throughput, and causes container ports to be accessible on the host without explicit exposure. Note that this means opting out of the network isolation normally provided to containers, refer to the Docker manual for more information.
You can also build k6 from source
This requires a working Go environment (Go 1.7 or later - set up) and you will also need git, make, node.js and a couple of other dependencies that you can install like this: npm i -g bower ember-cli
. When you have all prerequisites, you can build k6:
go get -u github.com/loadimpact/k6
(If you opt for cloning or updating through git pull
rather than go get
for whatever reason, note that you also need to do git submodule update --init
to get JS dependencies up to date.)
Step-by-step guide to build k6 from source
Following the below steps exactly should result in a working k6 executable. The only thing you need is Docker, or you may try with a clean Ubuntu 14.04 installation, in which case you can skip the first docker command below. First we set up our build environment:
docker run -it ubuntu:14.04 /bin/bash
apt-get update
apt-get install -y git make nodejs-legacy npm curl
curl https://storage.googleapis.com/golang/go1.7.4.linux-amd64.tar.gz | tar -C /usr/local -xzf -
export GOROOT=/usr/local/go
export PATH=$PATH:$GOROOT/bin
export GOPATH=$HOME/go
mkdir $GOPATH
npm install -g bower ember-cli@2.7.0
(quick coffee break opportunity here)
Then we're ready to build k6:
go get -d -u github.com/loadimpact/k6
cd $GOPATH/src/github.com/loadimpact/k6
make
(last chance for coffee)
You should now have a k6 binary in your current working directory.
Usage
k6 works with the concept of "virtual users", or "VUs". A VU is essentially a glorified while (true)
loop that runs a script over and over and reports stats or errors generated.
Let's say you've written a script called myscript.js
(you can copy the one from the top of this page), and you want to run it with 100 VUs for 30 seconds. You'd do something like this:
k6 run -u 100 -d 30s myscript.js
The first thing you might notice is that the duration is written "30s", not "30". This is because we're using Go's duration notation, which means 90s
, 1m30s
, 24h
and 2d
are all valid durations, and much more readable than if you had to convert everything to seconds.
The second thing you might notice (or maybe not, if you're just reading this) is k6 saying this when it starts:
web ui: http://127.0.0.1:6565/
This is the address to a built-in HTTP server serving a full-fledged web UI where you can view realtime statistics and errors. The default behaviour is to shut everything down (including the web UI) once a test execution has completed, but there is a -l/--linger flag you can pass to k6 run
that will cause it to stay running until killed (e.g. with CTRL-C). This can be useful if you want to view the results of the test in the web UI.
But the web UI is not the only thing this HTTP server does. It also exposes a REST API on the same port for controlling test execution, which you can call yourself with an HTTP client of your choice (curl, httpie, ...), or using the commandline wrappers - essentially every k6 command aside from run
wraps an API call. For example, this will scale the running test down to 50 VUs:
k6 scale 50
This is a quite powerful feature when combined with options like -d 0
/ --duration 0
, which causes the test to run indefinitely until told otherwise. You're fully in control of how your test is executed!
For more information, see the tutorials