• Stars
    star
    213
  • Rank 185,410 (Top 4 %)
  • Language
    Go
  • License
    MIT License
  • Created about 7 years ago
  • Updated over 6 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Blast is a simple tool for API load testing and batch jobs

Build Status Go Report Card codecov

Blast

  • Blast makes API requests at a fixed rate.
  • The number of concurrent workers is configurable.
  • The rate may be changed interactively during execution.
  • Blast is protocol agnostic, and adding a new worker type is trivial.
  • For load testing: random data can be added to API requests.
  • For batch jobs: CSV data can be loaded from local file or GCS bucket, and successful items from previous runs are skipped.

Installation

Mac

brew tap dave/blast
brew install blast

Linux

See the releases page

From source

go get -u github.com/dave/blast

Examples

Using the dummy worker to send at 20,000 requests per second (the dummy worker returns after a random wait, and occasionally returns errors):

blast --rate=20000 --workers=1000 --worker-type="dummy" --worker-template='{"min":25,"max":50}'

Using the http worker to request Google's homepage at one request per second (warning: this is making real http requests - don't turn the rate up!):

blast --rate=1 --worker-type="http" --payload-template='{"method":"GET","url":"http://www.google.com/"}'

Status

Blast prints a summary every ten seconds. While blast is running, you can hit enter for an updated summary, or enter a number to change the sending rate. Each time you change the rate a new column of metrics is created. If the worker returns a field named status in it's response, the values are summarised as rows.

Here's an example of the output:

Metrics
=======
Concurrency:      1999 / 2000 workers in use

Desired rate:     (all)        10000        1000         100
Actual rate:      2112         5354         989          100
Avg concurrency:  1733         1976         367          37
Duration:         00:40        00:12        00:14        00:12

Total
-----
Started:          84525        69004        14249        1272
Finished:         82525        67004        14249        1272
Mean:             376.0 ms     374.8 ms     379.3 ms     377.9 ms
95th:             491.1 ms     488.1 ms     488.2 ms     489.6 ms

200
---
Count:            79208 (96%)  64320 (96%)  13663 (96%)  1225 (96%)
Mean:             376.2 ms     381.9 ms     374.7 ms     378.1 ms
95th:             487.6 ms     489.0 ms     487.2 ms     490.5 ms

404
---
Count:            2467 (3%)    2002 (3%)    430 (3%)     35 (3%)
Mean:             371.4 ms     371.0 ms     377.2 ms     358.9 ms
95th:             487.1 ms     487.1 ms     486.0 ms     480.4 ms

500
---
Count:            853 (1%)     685 (1%)     156 (1%)     12 (1%)
Mean:             371.2 ms     370.4 ms     374.5 ms     374.3 ms
95th:             487.6 ms     487.1 ms     488.2 ms     466.3 ms

Current rate is 10000 requests / second. Enter a new rate or press enter to view status.

Rate?

Config

Blast is configured by config file, command line flags or environment variables. The --config flag specifies the config file to load, and can be json, yaml, toml or anything else that viper can read. If the config flag is omitted, blast searches for blast-config.xxx in the current directory, $HOME/.config/blast/ and /etc/blast/.

Environment variables and command line flags override config file options. Environment variables are upper case and prefixed with "BLAST" e.g. BLAST_PAYLOAD_TEMPLATE.

Templates

The payload-template and worker-template options accept values that are rendered using the Go text/template system. Variables of the form {{ .name }} or {{ "name" }} are replaced with data.

Additionally, several simple functions are available to inject random data which is useful in load testing scenarios:

  • {{ rand_int -5 5 }} - a random integer between -5 and 5.
  • {{ rand_float -5 5 }} - a random float between -5 and 5.
  • {{ rand_string 10 }} - a random string, length 10.

Workers

Worker is an interface that allows blast to easily be extended to support any protocol. See main.go for an example of how to build a command with your custom worker type.

Starter and Stopper are interfaces a worker can optionally satisfy to provide initialization or finalization logic. See httpworker and dummyworker for simple examples.

Examples

For load testing:

rate: 20000
workers: 1000
worker-type: "dummy"
payload-template:
  method: "POST"
  path: "/foo/?id={{ rand_int 1 10000000 }}"
worker-template:
  print: false
  base: "https://{{ .region }}.my-api.com"
  min: 10
  max: 20
worker-variants:
  - region: "europe-west1"
  - region: "us-east1"

For bulk API tasks:

# data would usually be the filename of a local CSV file, or an object in a GCS bucket. However, 
# for the purposes of this example, a CSV fragment is also accepted.
data: |
  user_name,action
  dave,subscribe
  john,subscribe
  pete,unsubscribe
  jimmy,unsubscribe
resume: true
log: "out.log"
rate: 100
workers: 20
worker-type: "dummy"
payload-template: 
  method: "POST"
  path: "/{{ .user_name }}/{{ .action }}/{{ .type }}/"
worker-template:  
  print: true
  base: "https://{{ .region }}.my-api.com"
  min: 250
  max: 500
payload-variants: 
  - type: "email"
  - type: "phone"
worker-variants: 
  - region: "europe-west1"
  - region: "us-east1"
log-data:
  - "user_name"
  - "action"
log-output: 
  - "status"

Configuration options

data

Data sets the the data file to load. If none is specified, the worker will be called repeatedly until interrupted (useful for load testing). Load a local file or stream directly from a GCS bucket with gs://{bucket}/{filename}.csv. Data should be in csv format, and if headers is not specified the first record will be used as the headers. If a newline character is found, this string is read as the data.

log

Log sets the filename of the log file to create / append to.

resume

Resume instructs the tool to load the log file and skip previously successful items. Failed items will be retried.

rate

Rate sets the initial rate in requests per second. Simply enter a new rate during execution to adjust this. (Default: 10 requests / second).

workers

Workers sets the number of concurrent workers. (Default: 10 workers).

worker-type

WorkerType sets the selected worker type. Register new worker types with the RegisterWorkerType method.

payload-template

PayloadTemplate sets the template that is rendered and passed to the worker Send method. When setting this by command line flag or environment variable, use a json encoded string.

Advanced configuration options

timeout

Timeout sets the deadline in the context passed to the worker. Workers must respect this the context cancellation. We exit with an error if any worker is processing for timeout + 1 second. (Default: 1 second).

headers

Headers sets the data file headers. If omitted, the first record of the csv data source is used. When setting this by command line flag or environment variable, use a json encoded string.

log-data

LogData sets an array of data fields to include in the output log. When setting this by command line flag or environment variable, use a json encoded string.

log-output

LogOutput sets an array of worker response fields to include in the output log. When setting this by command line flag or environment variable, use a json encoded string.

worker-template

WorkerTemplate sets a template to render and pass to the worker Start or Stop methods if the worker satisfies the Starter or Stopper interfaces. Use with worker-variants to configure several workers differently to spread load. When setting this by command line flag or environment variable, use a json encoded string.

worker-variants

WorkerVariants sets an array of maps that will cause each worker to be initialised with different data. When setting this by command line flag or environment variable, use a json encoded string.

payload-variants

PayloadVariants sets an array of maps that will cause each data item to be repeated with the provided data. When setting this by command line flag or environment variable, use a json encoded string.

Control by code

The blaster package may be used to start blast from code without using the command. Here's a some examples of usage:

ctx, cancel := context.WithCancel(context.Background())
b := blaster.New(ctx, cancel)
defer b.Exit()
b.SetWorker(func() blaster.Worker {
	return &blaster.ExampleWorker{
		SendFunc: func(ctx context.Context, self *blaster.ExampleWorker, in map[string]interface{}) (map[string]interface{}, error) {
			return map[string]interface{}{"status": 200}, nil
		},
	}
})
b.Headers = []string{"header"}
b.SetData(strings.NewReader("foo\nbar"))
stats, err := b.Start(ctx)
if err != nil {
	fmt.Println(err.Error())
	return
}
fmt.Printf("Success == 2: %v\n", stats.All.Summary.Success == 2)
fmt.Printf("Fail == 0: %v", stats.All.Summary.Fail == 0)
// Output:
// Success == 2: true
// Fail == 0: true
ctx, cancel := context.WithCancel(context.Background())
b := blaster.New(ctx, cancel)
defer b.Exit()
b.SetWorker(func() blaster.Worker {
	return &blaster.ExampleWorker{
		SendFunc: func(ctx context.Context, self *blaster.ExampleWorker, in map[string]interface{}) (map[string]interface{}, error) {
			return map[string]interface{}{"status": 200}, nil
		},
	}
})
b.Rate = 1000
wg := &sync.WaitGroup{}
wg.Add(1)
go func() {
	stats, err := b.Start(ctx)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	fmt.Printf("Success > 10: %v\n", stats.All.Summary.Success > 10)
	fmt.Printf("Fail == 0: %v", stats.All.Summary.Fail == 0)
	wg.Done()
}()
<-time.After(time.Millisecond * 100)
b.Exit()
wg.Wait()
// Output:
// Success > 10: true
// Fail == 0: true

To do

  • Adjust rate automatically in response to latency? PID controller?
  • Only use part of file: part i of j parts

More Repositories

1

jennifer

Jennifer is a code generator for Go
Go
3,055
star
2

dst

Decorated Syntax Tree - manipulate Go source with perfect fidelity.
Go
1,165
star
3

jsgo

GopherJS compiler, serving framework and CDN.
Go
267
star
4

courtney

Courtney is a coverage tool for Go
Go
150
star
5

wasmgo

Compiles Go to WASM and deploys to the jsgo.io CDN
Go
145
star
6

rebecca

Rebecca is a readme generator for Go
Go
111
star
7

play

jsgo playground: edit and run Go code in the browser, supporting arbitrary import paths
Go
50
star
8

brenda

Brenda is a boolean expression solver for Go AST
Go
44
star
9

html2vecty

Translate html to vecty syntax
Go
12
star
10

asm

High level assembly DSL
Go
8
star
11

forky

A tool to automate forking and modifying codebases
Go
7
star
12

services

Services for interacting with remote services (gcs, git, http etc.) shared between jsgo, play and frizz.
Go
7
star
13

youtube

Tool to upload videos directly from Google Drive to YouTube
Go
6
star
14

govpn

Go
5
star
15

libify

Convert any Go command line app into a library
Go
5
star
16

dropper

GopherJS package to accept files by drag+drop
Go
5
star
17

gpx

Quick util to manipulate GPX files
Go
4
star
18

flux

Vecty flux library
Go
4
star
19

stablegob

Fork of encoding/gob, with deterministic binary output
Go
4
star
20

dontstayin

I created dontstayin.com back in 2003. We peaked in 2005 with 10 employees, 1.5m uniques & 50m page views per month. We sold the company in 2009 and it was shut down by the new owners in 2012. You can see a documentary filmed in the early days here: https://vimeo.com/24485226. The code is here purely for posterity - it is filled with horrors.
C#
4
star
21

golib

Go
3
star
22

jast

jast is an experimental tool for converting AST to jennifer
Go
2
star
23

patsy

Patsy is a package helper for Go.
Go
2
star
24

kerr

Go errors, but a bit more testable
Go
2
star
25

gopackages

Go utils for for package paths, package names and file paths
Go
2
star
26

sorter

Simplify sorting in Go
Go
2
star
27

frizz

The frizz editor - not ready for public consumption yet
Go
2
star
28

groupshare

Group Share
Dart
2
star
29

astrid

Astrid is a collection of AST utilities for Go
Go
2
star
30

splitter

GopherJS wrapper for Split.js
Go
1
star
31

img

Compress image files in the browser with GopherJS - jsgo.io/dave/img
Go
1
star
32

protod

Protocol Buffer Deltas
Dart
1
star
33

iot

Go
1
star
34

saver

GopherJS package to save files using the FileSaver.js library
Go
1
star
35

dbcombo

DbCombo was mildly successful when I launched in 2001, but it was shut down and deleted in about 2006. I was amazed to find we still have an active user in 2017!
C#
1
star
36

geny

A code generator for Go
Go
1
star
37

refreshable_reorderable_list

A fork of ReorderableList which adds the physics property needed for RefreshIndicator to work
Dart
1
star
38

cfag-server

Dockerfile
1
star
39

oak

A generic CMS in Meteor
JavaScript
1
star
40

scrapy

Web scraper test project
Go
1
star
41

wildernessprime

CSS
1
star