2013-09-08 03:15:52 +01:00
|
|
|
# Vegeta [](http://travis-ci.org/tsenart/vegeta)
|
2013-08-13 18:51:00 +02:00
|
|
|
|
|
|
|
|
Vegeta is a versatile HTTP load testing tool built out of need to drill
|
2013-08-14 17:31:22 +02:00
|
|
|
HTTP services with a constant request rate.
|
2013-08-17 16:14:08 +02:00
|
|
|
It can be used both as a command line utility and a library.
|
2013-08-13 18:51:00 +02:00
|
|
|
|
2013-11-07 15:31:00 +00:00
|
|
|
*This fork ads support to attacking with multiple rates and a csv reporter suitable for import into spreadsheet applications.*
|
2013-08-14 15:18:05 +02:00
|
|
|
|
2013-11-07 15:30:16 +00:00
|
|
|

|
2013-08-18 03:42:40 +02:00
|
|
|
|
|
|
|
|
### Source
|
2013-08-13 18:51:00 +02:00
|
|
|
You need go installed and `GOBIN` in your `PATH`. Once that is done, run the
|
|
|
|
|
command:
|
|
|
|
|
```shell
|
2013-08-18 02:01:40 +02:00
|
|
|
$ go get github.com/tsenart/vegeta
|
2013-08-13 18:51:00 +02:00
|
|
|
$ go install github.com/tsenart/vegeta
|
|
|
|
|
```
|
|
|
|
|
|
2013-09-11 14:35:04 +01:00
|
|
|
## Usage examples
|
|
|
|
|
```shell
|
2013-11-07 15:30:16 +00:00
|
|
|
$ echo "GET http://localhost/" | vegeta rapid -rates=100,200,300 -duration=10s | vegeta report -reporter=csv
|
2013-09-11 14:35:04 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Usage manual
|
2013-08-13 18:51:00 +02:00
|
|
|
```shell
|
|
|
|
|
$ vegeta -h
|
2013-09-11 14:35:04 +01:00
|
|
|
Usage: vegeta [globals] <command> [options]
|
|
|
|
|
|
|
|
|
|
Commands:
|
|
|
|
|
attack Hit the targets
|
|
|
|
|
report Report the results
|
2013-11-07 15:30:16 +00:00
|
|
|
rapid Hit the targets with multiple rates
|
2013-09-11 14:35:04 +01:00
|
|
|
|
|
|
|
|
Globals:
|
|
|
|
|
-cpus=8 Number of CPUs to use
|
2013-08-13 18:51:00 +02:00
|
|
|
```
|
|
|
|
|
|
2013-09-08 22:45:14 +01:00
|
|
|
#### -cpus
|
|
|
|
|
Specifies the number of CPUs to be used internally.
|
|
|
|
|
It defaults to the amount of CPUs available in the system.
|
|
|
|
|
|
2013-09-11 14:35:04 +01:00
|
|
|
### attack
|
|
|
|
|
```shell
|
|
|
|
|
$ vegeta attack -h
|
|
|
|
|
Usage of attack:
|
|
|
|
|
-duration=10s: Duration of the test
|
2013-09-21 18:46:09 +02:00
|
|
|
-header=: Targets request header
|
2013-09-11 14:35:04 +01:00
|
|
|
-ordering="random": Attack ordering [sequential, random]
|
|
|
|
|
-output="stdout": Output file
|
|
|
|
|
-rate=50: Requests per second
|
|
|
|
|
-targets="stdin": Targets file
|
|
|
|
|
```
|
|
|
|
|
|
2013-08-13 18:51:00 +02:00
|
|
|
#### -duration
|
|
|
|
|
Specifies the amount of time to issue request to the targets.
|
|
|
|
|
The internal concurrency structure's setup has this value as a variable.
|
|
|
|
|
The actual run time of the test can be longer than specified due to the
|
|
|
|
|
responses delay.
|
|
|
|
|
|
2013-09-21 18:46:09 +02:00
|
|
|
#### -header
|
|
|
|
|
Specifies a request header to be used in all targets defined.
|
|
|
|
|
You can specify as many as needed by repeating the flag.
|
|
|
|
|
|
2013-08-13 18:51:00 +02:00
|
|
|
#### -ordering
|
|
|
|
|
Specifies the ordering of target attack. The default is `random` and
|
|
|
|
|
it will randomly pick one of the targets per request without ever choosing
|
|
|
|
|
that target again.
|
|
|
|
|
The other option is `sequential` and it does what you would expect it to
|
|
|
|
|
do.
|
|
|
|
|
|
2013-08-14 17:48:51 +02:00
|
|
|
#### -output
|
2013-09-11 14:35:04 +01:00
|
|
|
Specifies the output file to which the binary results will be written
|
|
|
|
|
to. Made to be piped to the report command input. Defaults to stdout.
|
2013-08-14 17:48:51 +02:00
|
|
|
|
2013-08-13 18:51:00 +02:00
|
|
|
#### -rate
|
2013-08-15 13:56:36 +02:00
|
|
|
Specifies the requests per second rate to issue against
|
|
|
|
|
the targets. The actual request rate can vary slightly due to things like
|
|
|
|
|
garbage collection, but overall it should stay very close to the specified.
|
2013-08-13 18:51:00 +02:00
|
|
|
|
2013-09-11 14:35:04 +01:00
|
|
|
#### -targets
|
2013-10-23 13:07:45 +02:00
|
|
|
Specifies the attack targets in a line separated file, defaulting to stdin.
|
2013-09-11 14:35:04 +01:00
|
|
|
The format should be as follows.
|
|
|
|
|
```
|
|
|
|
|
GET http://goku:9090/path/to/dragon?item=balls
|
|
|
|
|
GET http://user:password@goku:9090/path/to
|
|
|
|
|
HEAD http://goku:9090/path/to/success
|
|
|
|
|
...
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### report
|
|
|
|
|
```
|
|
|
|
|
$ vegeta report -h
|
|
|
|
|
Usage of report:
|
2013-09-12 05:35:54 +01:00
|
|
|
-input="stdin": Input files (comma separated)
|
2013-09-11 14:35:04 +01:00
|
|
|
-output="stdout": Output file
|
2013-09-23 01:59:20 +02:00
|
|
|
-reporter="text": Reporter [text, json, plot]
|
2013-09-11 14:35:04 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### -input
|
2013-09-12 05:35:54 +01:00
|
|
|
Specifies the input files to generate the report of, defaulting to stdin.
|
|
|
|
|
These are the output of vegeta attack. You can specify more than one (comma
|
|
|
|
|
separated) and they will be merged and sorted before being used by the
|
|
|
|
|
reports.
|
2013-09-11 14:35:04 +01:00
|
|
|
|
|
|
|
|
#### -output
|
|
|
|
|
Specifies the output file to which the report will be written to.
|
|
|
|
|
|
2013-08-13 18:51:00 +02:00
|
|
|
#### -reporter
|
2013-09-11 14:35:04 +01:00
|
|
|
Specifies the kind of report to be generated. It defaults to text.
|
|
|
|
|
|
|
|
|
|
##### text
|
2013-08-17 20:05:07 +02:00
|
|
|
```
|
2013-10-04 21:46:16 +02:00
|
|
|
Requests [total] 1200
|
2013-10-29 13:48:37 +01:00
|
|
|
Duration [total] 1.998307684s
|
2013-10-05 23:14:36 +02:00
|
|
|
Latencies [mean, 95, 99, max] 223.340085ms, 326.913687ms, 416.537743ms, 7.788103259s
|
2013-10-04 21:46:16 +02:00
|
|
|
Bytes In [total, mean] 3714690, 3095.57
|
|
|
|
|
Bytes Out [total, mean] 0, 0.00
|
|
|
|
|
Success [ratio] 55.42%
|
|
|
|
|
Status Codes [code:count] 0:535 200:665
|
2013-08-17 20:05:07 +02:00
|
|
|
Error Set:
|
2013-10-04 21:46:16 +02:00
|
|
|
Get http://localhost:6060: dial tcp 127.0.0.1:6060: connection refused
|
|
|
|
|
Get http://localhost:6060: read tcp 127.0.0.1:6060: connection reset by peer
|
|
|
|
|
Get http://localhost:6060: dial tcp 127.0.0.1:6060: connection reset by peer
|
|
|
|
|
Get http://localhost:6060: write tcp 127.0.0.1:6060: broken pipe
|
|
|
|
|
Get http://localhost:6060: net/http: transport closed before response was received
|
|
|
|
|
Get http://localhost:6060: http: can't write HTTP request on broken connection
|
2013-08-17 20:05:07 +02:00
|
|
|
```
|
2013-10-04 21:46:16 +02:00
|
|
|
|
2013-09-11 14:35:04 +01:00
|
|
|
##### json
|
2013-09-10 13:45:01 +01:00
|
|
|
```json
|
|
|
|
|
{
|
2013-10-05 22:14:25 +02:00
|
|
|
"latencies": {
|
|
|
|
|
"mean": 9093653647,
|
2013-10-05 23:14:36 +02:00
|
|
|
"95th": 12553709381,
|
|
|
|
|
"99th": 12604629125,
|
|
|
|
|
"max": 12604629125
|
2013-10-05 22:14:25 +02:00
|
|
|
},
|
|
|
|
|
"bytes_in": {
|
|
|
|
|
"total": 782040,
|
|
|
|
|
"mean": 651.7
|
|
|
|
|
},
|
|
|
|
|
"bytes_out": {
|
|
|
|
|
"total": 0,
|
|
|
|
|
"mean": 0
|
|
|
|
|
},
|
2013-10-29 13:48:37 +01:00
|
|
|
"duration": 1998307684,
|
2013-10-05 22:14:25 +02:00
|
|
|
"requests": 1200,
|
|
|
|
|
"success": 0.11666666666666667,
|
2013-09-10 13:45:01 +01:00
|
|
|
"status_codes": {
|
2013-10-05 22:14:25 +02:00
|
|
|
"0": 1060,
|
|
|
|
|
"200": 140
|
2013-09-10 13:45:01 +01:00
|
|
|
},
|
2013-10-05 22:14:25 +02:00
|
|
|
"errors": [
|
|
|
|
|
"Get http://localhost:6060: dial tcp 127.0.0.1:6060: operation timed out"
|
|
|
|
|
]
|
2013-09-10 13:45:01 +01:00
|
|
|
}
|
|
|
|
|
```
|
2013-09-23 01:59:20 +02:00
|
|
|
##### plot
|
|
|
|
|
Generates an HTML5 page with an interactive plot based on
|
|
|
|
|
[Dygraphs](http://dygraphs.com).
|
|
|
|
|
Click and drag to select a region to zoom into. Double click to zoom
|
|
|
|
|
out.
|
|
|
|
|
Input a different number on the bottom left corner input field
|
|
|
|
|
to change the moving average window size (in data points).
|
|
|
|
|
|
|
|
|
|

|
2013-08-13 18:51:00 +02:00
|
|
|
|
|
|
|
|
|
2013-08-17 16:14:08 +02:00
|
|
|
## Usage (Library)
|
|
|
|
|
```go
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
vegeta "github.com/tsenart/vegeta/lib"
|
|
|
|
|
"time"
|
2013-09-09 01:49:57 +01:00
|
|
|
"fmt"
|
2013-08-17 16:14:08 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func main() {
|
2013-08-20 18:00:32 +08:00
|
|
|
targets, _ := vegeta.NewTargets([]string{"GET http://localhost:9100/"})
|
2013-08-17 16:14:08 +02:00
|
|
|
rate := uint64(100) // per second
|
|
|
|
|
duration := 4 * time.Second
|
|
|
|
|
|
2013-09-09 01:49:57 +01:00
|
|
|
results := vegeta.Attack(targets, rate, duration)
|
2013-10-04 21:46:16 +02:00
|
|
|
metrics := vegeta.NewMetrics(results)
|
2013-08-17 16:14:08 +02:00
|
|
|
|
2013-10-04 21:46:16 +02:00
|
|
|
fmt.Printf("Mean latency: %s", metrics.Latencies.Mean)
|
2013-08-17 16:14:08 +02:00
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2013-08-14 22:57:14 +02:00
|
|
|
#### Limitations
|
|
|
|
|
There will be an upper bound of the supported `rate` which varies on the
|
|
|
|
|
machine being used.
|
|
|
|
|
You could be CPU bound (unlikely), memory bound (more likely) or
|
|
|
|
|
have system resource limits being reached which ought to be tuned for
|
|
|
|
|
the process execution. The important limits for us are file descriptors
|
|
|
|
|
and processes. On a UNIX system you can get and set the current
|
|
|
|
|
soft-limit values for a user.
|
|
|
|
|
```shell
|
|
|
|
|
$ ulimit -n # file descriptors
|
|
|
|
|
2560
|
|
|
|
|
$ ulimit -u # processes / threads
|
|
|
|
|
709
|
|
|
|
|
```
|
|
|
|
|
Just pass a new number as the argument to change it.
|
2013-08-13 18:51:00 +02:00
|
|
|
|
|
|
|
|
## Licence
|
2013-08-17 20:13:05 +02:00
|
|
|
```
|
2013-08-17 20:10:59 +02:00
|
|
|
The MIT License (MIT)
|
|
|
|
|
|
|
|
|
|
Copyright (c) 2013 Tomás Senart
|
|
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
|
|
|
this software and associated documentation files (the "Software"), to deal in
|
|
|
|
|
the Software without restriction, including without limitation the rights to
|
|
|
|
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
|
|
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
|
|
|
subject to the following conditions:
|
|
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
|
|
|
copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
|
|
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
|
|
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
|
|
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
|
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
2013-08-17 20:13:05 +02:00
|
|
|
```
|