2012-07-26 13:29:03 +00:00
# Yandex Tank
## Description
2012-07-26 13:15:10 +00:00
Yandex.Tank is a console HTTP load testing instrument.
2012-07-23 11:05:58 +00:00
2012-07-26 13:29:03 +00:00
### Installation and Configuration
2012-07-26 13:15:10 +00:00
You should add proper repository to source.list on Debian-based environment.
For instance, on Lucid:
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
deb http://dist.yandex.ru/phantom lucid/amd64/
# on 32bit system use i386 instead of amd64
#deb http://dist.yandex.ru/phantom lucid/i386/
deb http://dist.yandex.ru/phantom common/all/
2012-07-26 13:29:03 +00:00
```
```sudo apt-get update & & sudo apt-get install yandex-load-tank-base```
2012-07-26 13:15:10 +00:00
All needed packets will be installed.
For a mild load tests (less then 1000rps) an average laptop with 34/64bit Ubuntu (Lucid/Precise) will be sufficient. The tank could be easily used in virtual machine if queries aren't heavy and the load isn't big.
Otherwise it is recommended to request from your admin a physical server or a more capable virtual machine.
2012-07-26 13:29:03 +00:00
### Firewall
2012-07-26 13:15:10 +00:00
Before test execution, please, check service availability. If service is running on server with IP x.x.x.x and listen TCP port zz, check instructions are:
2012-07-26 13:29:03 +00:00
```telnet x.x.x.x zz```
2012-07-26 13:15:10 +00:00
If everything OK, you'll see:
2012-07-26 13:29:03 +00:00
```$ telnet 23.23.23.23 80
2012-07-26 13:15:10 +00:00
Trying 23.23.23.23...
Connected to 23.23.23.23.
2012-07-26 13:29:03 +00:00
Escape character is '^]'.```
2012-07-26 13:15:10 +00:00
Otherwise:
2012-07-26 13:29:03 +00:00
```$ telnet 8.8.8.8 80
2012-07-26 13:15:10 +00:00
Trying 8.8.8.8...
2012-07-26 13:29:03 +00:00
telnet: Unable to connect to remote host: Connection timed out```
2012-07-26 13:15:10 +00:00
(it's just example, programs nc/nmap/wget/curl could be used as well, but not ping!)
2012-07-26 13:29:03 +00:00
### Routing
2012-07-26 13:15:10 +00:00
OK, service is reachable, the next thing you should know is how far the Yandex.Tank is located from testing service. Heavy load can hang up, reboot switch, or at least lead to losses in network, so test results would be distorted. Be careful. Path estimation could be done by execution of 'tracepath' command or it analogs (tracert/traceroute) on server with Yandex.Tank.
2012-07-26 13:29:03 +00:00
```$ tracepath 23.23.23.24
2012-07-26 13:15:10 +00:00
1: tank.example.com (23.23.23.23) 0.084ms pmtu 1450
1: target.load.example.com (23.23.23.24) 20.919ms reached
1: target.example.com (23.23.23.24) 0.128ms reached
Resume: pmtu 1450 hops 1 back 64
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
hops 1 means that tank and target are in closest location.
2012-07-26 13:29:03 +00:00
```$ tracepath 24.24.24.24
2012-07-26 13:15:10 +00:00
1: 1.example.com (124.24.24.24) 0.084ms pmtu 1450
1: 2.example.com (24.124.24.24) 0.276ms
1: 3.example.com (24.24.124.24) 0.411ms
2: 4.example.com (24.24.24.124) 0.514ms
3: 5.example.com (241.24.24.24) 10.690ms
4: 6.example.com (24.241.24.24) 0.831ms asymm 3
5: 7.example.com (24.24.241.24) 0.512ms
6: 8.example.com (24.24.24.241) 0.525ms asymm 5
7: no reply
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
In that example it is better to find another, more closer located tank.
2012-07-26 13:29:03 +00:00
### Tunning
2012-07-26 13:15:10 +00:00
For the top most performance the source server should have tuned system limits
ulimit -n 30000
net.ipv4.tcp_max_tw_buckets = 65536
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_max_syn_backlog = 131072
net.ipv4.tcp_syn_retries = 3
net.ipv4.tcp_synack_retries = 3
net.ipv4.tcp_retries1 = 3
net.ipv4.tcp_retries2 = 8
net.ipv4.tcp_rmem = 16384 174760 349520
net.ipv4.tcp_wmem = 16384 131072 262144
net.ipv4.tcp_mem = 262144 524288 1048576
net.ipv4.tcp_max_orphans = 65536
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_low_latency = 1
net.ipv4.tcp_syncookies = 0
2012-07-26 13:29:03 +00:00
## Usage
2012-07-26 13:15:10 +00:00
So, you've installed Yandex.Tank to a proper server, close to target, access is permitted.
How to make a test?
2012-07-26 13:29:03 +00:00
### First Step
2012-07-26 13:15:10 +00:00
Create on server with Yandex.Tank file, e.g. load.conf
2012-07-26 13:29:03 +00:00
``` > load.conf```
2012-07-26 13:15:10 +00:00
Write into it
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
address=23.23.23.23:80 #Target 's address and port .
2012-07-26 13:29:03 +00:00
load = #load scheme ```!!Attention: IP address allowed only, not FQDN!!
2012-07-26 13:15:10 +00:00
Yandex.Tank have 3 primitives for describing load scheme:
1. [step (a,b,step,dur)] #Makes stepped load, where a,b are start/end load values, step - increment value, dur - step duration.
2. [line (a,b,dur)] #Makes linear load, where a,b are start/end load, dur - the time for linear load increase from a to b.
3. [const (load,dur)] #Makes constant load. load - rps amount, dur - load duration.
[const (a/b,dur)] # Fractional load, a/b rps, where a >= 0, b > 0.
Note:
const(0, 10) - 0 rps for 10 seconds, in fact 10s pause in test
step and line could be used with increasing and decreasing intensity:
step(25, 5, 5, 60) - stepped load from 25 to 5 rps, with 5 rps steps, step duration 60s.
step(5, 25, 5, 60) - stepped load from 5 to 25 rps, with 5 rps steps, step duration 60s
line(100, 1, 10m) - linear load from 100 to 1 rps, duration - 10 minutes
line(1, 100, 10m) - linear load from 1 to 100 rps, duration - 10 minutes
Time duration could be defined in second (without dimension), minutes (m) and hours (h). For example: 27h103m645
For a test with constant load at 10rps for 10 minutes, load.conf should have next lines:
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
address=23.23.23.23:80 #Target 's address and port
load = const (10,10m) #Load scheme
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
Voilà, Yandex.Tank setup is done
2012-07-26 13:29:03 +00:00
### Requests prepairing
2012-07-26 13:15:10 +00:00
There are two ways of requests declaration
2012-07-26 13:29:03 +00:00
#### Urls listed in load.conf or in separate file (so called uri-style)
2012-07-26 13:15:10 +00:00
2012-07-26 13:29:03 +00:00
##### Requests in load.conf
2012-07-26 13:15:10 +00:00
Update configuration file with HTTP headers and URIs:
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
address=23.23.23.23:80 #Target 's address and port
load = const (10,10m) #Load scheme
# Headers and URIs for GET requests
header_http = 1.1
header_connection = close
header_host = target.example.com
uri = /
uri = /buy
uri = /sdfg?sdf=rwerf
uri = /sdfbv/swdfvs/ssfsf
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
Parameters **header_** * define headers values.
**uri** contain uri, which should be used for requests generation.
2012-07-26 13:29:03 +00:00
##### Requests in file
2012-07-26 13:15:10 +00:00
File ammo.txt with declared requests:
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
[Connection: close]
[Host: target.example.com]
[Cookies: None]
/?drg
/
/buy
/buy/?rt=0& station_to=7& station_from=9
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
File begins with optional lines [...], containing headers which will be added to every request. After that section there is URI list. Every URI must be in a new line, with leading '/'.
2012-07-26 13:29:03 +00:00
#### Request "as-is" in file
2012-07-26 13:15:10 +00:00
For more complex requests, like POST, you'll have to create special file.
File format is:
[size_of_request] [tag]\n
[body_request]
\r\n
< {**Example GET:**
73 good
GET / HTTP/1.0
Host: xxx.tanks.example.com
User-Agent: xxx (shell 1)
77 bad
GET /abra HTTP/1.0
Host: xxx.tanks.example.com
User-Agent: xxx (shell 1)
78 unknown
GET /ab ra HTTP/1.0
Host: xxx.tanks.example.com
User-Agent: xxx (shell 1)
...
}>
< {**Example POST:**
2012-07-26 13:29:03 +00:00
```904
2012-07-26 13:15:10 +00:00
POST /upload/2 HTTP/1.0
Content-Length: 801
Host: xxxxxxxxx.dev.example.com
User-Agent: xxx (shell 1)
^.^........W.j^1^.^.^.²..^^.i.^B.P..-!(.l/Y..V^. ...L?...S'NR.^^vm...3Gg@s...d'.\^.5N.$NF^,.Z^.aTE^.
._.[..k#L^ƨ`\RE.J.< . !,. q5 . F ^՚ iΔĬq ..^ 6 .. P .. тH .`.. i2
.".uuzs^^F2...Rh.& .U.^^..J.P@.A......x..lǝy^?.u.p{4..g...m.,..R^.^.^......].^^.^J...p.ifTF0< .s.9V.o5 < . . % ! 6ļS . ƐǢ . . 㱋 . . . . C ^ & . . . . . ^ . ^ y . . . v ] ^ YT . 1 . # K . ibc . . . ^ . 26 . . . . . 7 .
b.$...j6.٨f...W.R7.^1.3....K`%.& ^..d..{{ l0..^\..^X.g.^.r.(!.^^...4.1.$\ .%.8$(.n& ..^^q.,.Q..^.D^.].^.R9.kE.^.$^.I..< ..B ^..^. h ^^ C .^ E .|.... 3o ^.@.. Z .^. s .$[ v .
527
POST /upload/3 HTTP/1.0
Content-Length: 424
Host: xxxxxxxxx.dev.example.com
User-Agent: xxx (shell 1)
^.^........QMO.0^.++^zJw.ر^$^.^Ѣ.^V.J....vM.8r& .T+...{@pk%~C.G../z顲^.7....l...-.^W"cR..... .& ^?u.U^^.^.....{^.^..8.^.^.I.EĂ.p...'^.3.Tq..@R8....RAiBU..1.Bd*".7+.
2012-07-26 13:29:03 +00:00
.Ol.j=^.3..n....wp..,Wg.y^.T..~^..```
2012-07-26 13:15:10 +00:00
}>
< {**Example POST multipart:**
2012-07-26 13:29:03 +00:00
```533
2012-07-26 13:15:10 +00:00
POST /updateShopStatus? HTTP/1.0
User-Agent: xxx/1.2.3
Host: xxxxxxxxx.dev.example.com
Keep-Alive: 300
Content-Type: multipart/form-data; boundary=AGHTUNG
Content-Length:334
--AGHTUNG
Content-Disposition: form-data; name="host"
load-test-shop-updatestatus.ru
--AGHTUNG
Content-Disposition: form-data; name="user_id"
1
--AGHTUNG
Content-Disposition: form-data; name="wsw-fields"
< wsw-fields > < wsw-field name = "moderate-code" > < wsw-value > disable< / wsw-value > < / wsw-field > < / wsw-fields >
--AGHTUNG--
2012-07-26 13:29:03 +00:00
Connection: Close```
2012-07-26 13:15:10 +00:00
}>
size_of_request – request size in bytes, that amount of data will be send over network. '\r\n' symbols after body_requests are ignored and not sent anywhere.
2012-07-26 13:29:03 +00:00
### Run Test!
2012-07-26 13:15:10 +00:00
1. Uri are in load.conf
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
lunapark
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
2. Uri are in ammo.txt
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
lunapark ammo.txt
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
Yandex.Tank detects requests format and generates ultimate requests versions.
'lunapark' here - inherited name of Yandex.Tank.
If Yandex.Tank has been installed properly and configuration file is correct, the load will be given in next few seconds.
2012-07-26 13:29:03 +00:00
### Results
2012-07-26 13:15:10 +00:00
During test execution you are shown HTTP and net errors, answers time distribution, progressbar and other interesting data.
At the same time file phout.txt is being written, which could be analyzed later.
2012-07-26 13:29:03 +00:00
### Tags
2012-07-26 13:15:10 +00:00
Requests could be grouped and marked by some word named 'tag'
Example of file with requests and tags:
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
73 good
GET / HTTP/1.0
Host: xxx.tanks.example.com
User-Agent: xxx (shell 1)
77 bad
GET /abra HTTP/1.0
Host: xxx.tanks.example.com
User-Agent: xxx (shell 1)
78 unknown
GET /ab ra HTTP/1.0
Host: xxx.tanks.example.com
User-Agent: xxx (shell 1)
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
RESTRICTION: latin letters allowed only.
2012-07-26 13:29:03 +00:00
### SSL
2012-07-26 13:15:10 +00:00
For SSL activation add 'ssl = 1' to load.conf. Don't forget to change port number to appropriate value.
Now, our basic config looks like that:
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
address=23.23.23.23:443 #Target 's address and port
load = const (10,10m) #Load scheme
ssl=1
2012-07-26 13:29:03 +00:00
```
### Autostop
2012-07-26 13:15:10 +00:00
Autostop is ability to automatically halt test execution if some conditions are reached.
HTTP and Net codes conditions:
There is an option to define specific codes (404,503,100) as well as code groups (3xx, 5xx, xx).
Also you can define relative threshold (percent from the whole amount of answer per second) or absolute (amount of answers with specified code per second).
Examples:
[autostop = http(4xx,25%,10)] – stop test, if amount of 4xx http codes in every second of last 10s period exceeds 25% of answers (relative threshold)
[autostop = net(101,25,10)] – stop test, if amount of 101 net-codes in every second of last 10s period is more than 25 (absolute threshold)
[autostop = net(xx,25,10)] – stop test, if amount of non-zero net-codes in every second of last 10s period is more than 25 (absolute threshold)
Average time conditions:
Example:
[autostop = time(1500,15)] – stop test, if average answer time exceeds 1500ms
So, if we want to stop test when all answers in 1 second period are 5xx, add autostop line to load.conf:
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
address=23.23.23.23:443 #Target 's address and port
load = const (10,10m) #Load schemessl=1
autostop = http(5xx,100%,1)
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
2012-07-26 13:29:03 +00:00
### Logging
2012-07-26 13:15:10 +00:00
Looking into target's answers is quite useful in debugging. For doing that add 'writelog = 1' to load.conf.
ATTENTION: Writing answers on high load leads to intensive disk i/o usage and can affect test accuracy.
Log format:
< [< metrics >
< body_request >
< body_answer ] >
Where metrics are:
size_in size_out response_time(interval_real) interval_event net_code
(request size, answer size, response time, time to wait for response from the server, answer network code)
Example:
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
user@tank:~$ head answ_*.txt
553 572 8056 8043 0
GET /create-issue HTTP/1.1
Host: target.yandex.net
User-Agent: tank
Accept: */*
Connection: close
HTTP/1.1 200 OK
Content-Type: application/javascript;charset=UTF-8
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
Current load.conf is:
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
instances=10
address=23.23.23.23:443 #Target 's address and port
load = const (10,10m) #Load scheme
ssl=1
autostop = http(5xx,100%,1)
writelog=1
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
2012-07-26 13:29:03 +00:00
### Results in phout
2012-07-26 13:15:10 +00:00
phout.txt - is a phantom written per-request log. It could be used for separate analyze (Excel/gnuplot/etc)
14th phantom writes next fields to phout.txt: time, tag, interval_real, connect_time, send_time, latency, receive_time, interval_event, size_out, size_in, net_code proto_code
Phout example:
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
1326453006.582 1510 934 52 384 140 1249 37 478 0 404
1326453006.582 others 1301 674 58 499 70 1116 37 478 0 404
1326453006.587 heavy 377 76 33 178 90 180 37 478 0 404
1326453006.587 294 47 27 146 74 147 37 478 0 404
1326453006.588 345 75 29 166 75 169 37 478 0 404
1326453006.590 276 72 28 119 57 121 53 476 0 404
1326453006.593 255 62 27 131 35 134 37 478 0 404
1326453006.594 304 50 30 147 77 149 37 478 0 404
1326453006.596 317 53 33 158 73 161 37 478 0 404
1326453006.598 257 58 32 106 61 110 37 478 0 404
1326453006.602 315 59 27 160 69 161 37 478 0 404
1326453006.603 256 59 33 107 57 110 53 476 0 404
2012-07-26 13:29:03 +00:00
1326453006.605 241 53 26 130 32 131 37 478 0 404```
2012-07-26 13:15:10 +00:00
2012-07-26 13:29:03 +00:00
### Graph and statistics
2012-07-26 13:15:10 +00:00
Under construction, not implemented yet
2012-07-26 13:29:03 +00:00
### Custom timings
2012-07-26 13:15:10 +00:00
time_periods = 10 45 50 100 150 300 500 1s 1500 2s 3s 10s # the last value - 10s is considered as connect timeout.
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
instances=10
address=23.23.23.23:443 #Target 's address and port
load = const (10,10m) #Load scheme
ssl=1
autostop = http(5xx,100%,1)
writelog=1
time_periods = 10 45 50 100 150 300 500 1s 1500 2s 3s 10s # the last value - 10s is considered as connect timeout.
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
2012-07-26 13:29:03 +00:00
### Threads limit
2012-07-26 13:15:10 +00:00
instances=N limits number of connects/threads.
Test with 10 threads:
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
instances=10
address=23.23.23.23:443 #Target 's address and port
load = const (10,10m) #Load scheme
ssl=1
autostop = http(5xx,100%,1)
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
2012-07-26 13:29:03 +00:00
### Threads manipulating
2012-07-26 13:15:10 +00:00
instances_schedule = < instances increasing scheme > # Test with active instances schedule will be performed if load scheme is not defined. Bear in mind that active instances number cannot be decreased and final number of them must be equal to general instances number.
load.conf example:
2012-07-26 13:29:03 +00:00
```instances=10
2012-07-26 13:15:10 +00:00
instances_schedule = line(1,10,10m)
address=23.23.23.23:443 #Target 's address and port
#load = const (10,10m) #Load scheme
ssl=1
2012-07-26 13:29:03 +00:00
autostop = http(5xx,100%,1)```
2012-07-26 13:15:10 +00:00
2012-07-26 13:29:03 +00:00
### Custom stateless protocol
2012-07-26 13:15:10 +00:00
In necessity of testing stateless HTTP-like protocol, Yandex.Tank's HTTP parser could be switched off, providing ability to generate load with any data, receiving any answer in return.
To do that add 'tank_type = 2'. !!Indispensable condition: Connection close must be initiated by remote side!!
load.conf example:
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
instances=10
address=23.23.23.23:443 #Target 's address and port
load = const (10,10m) #Load scheme
ssl=1
autostop = http(5xx,100%,1)
#tank_type=2 # Parameter Nonna is commented for compatibility reasons.
2012-07-26 13:29:03 +00:00
```
### Gatling
2012-07-26 13:15:10 +00:00
If server with installed Yandex.Tank have several IPs, they could be used to avoid outcome port shortage.
gatling_ip = 23.23.23.24 23.23.23.25
Load.conf:
2012-07-26 13:29:03 +00:00
```instances=10
2012-07-26 13:15:10 +00:00
address=23.23.23.23:443 #Target 's address and port
load = const (10,10m) #Load scheme
ssl=1
autostop = http(5xx,100%,1)
writelog=1
time_periods = 10 45 50 100 150 300 500 1s 1500 2s 3s 10s # the last value - 10s is considered as connect timeout.
#gatling_ip = 23.23.23.24 23.23.23.26 # Commented, ips are listed as example
#tank_type=2 # Parameter Nonna is commented for compatibility reasons.
2012-07-26 13:29:03 +00:00
```
2012-07-26 13:15:10 +00:00
**exec with -g key**
2012-07-26 13:29:03 +00:00
### Sources
2012-07-26 13:15:10 +00:00
Yandex.Tank sources ((https://github.com/yandex-load/yandex-tank here)).
2012-07-26 13:29:03 +00:00
### load.conf.example
```
2012-07-26 13:15:10 +00:00
# Lunapark config file
address=23.23.23.23:443 #Target 's address and port
load = const (10,10m) #Load scheme
# Headers and URIs for GET requests
header_http = 1.1
header_connection = close
header_host = target.example.com
uri = /
#ssl=1
#autostop = http(5xx,100%,1)
#instances=10
#writelog=1
#time_periods = 10 45 50 100 150 300 500 1s 1500 2s 3s 10s # the last value - 10s is considered as connect timeout.
#instances_schedule = line (1,1000,10m)
#tank_type=2
#gatling_ip = 141.8.153.82 141.8.153.81
2012-07-26 13:29:03 +00:00
```