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
Owner
Similar Resources

An Ingress controller for Kubernetes using NGINX as a reverse proxy and load balancer

NGINX Ingress Controller Overview ingress-nginx is an Ingress controller for Kubernetes using NGINX as a reverse proxy and load balancer. Learn more a

Nov 15, 2021

k6 extension to load test Apache Kafka with support for Avro messages and SASL Authentication

xk6-kafka This project is a k6 extension that can be used to load test Kafka, using a producer. Per each connection to Kafka, many messages can be sen

Dec 7, 2021

Sesame: an Ingress controller for Kubernetes that works by deploying the Envoy proxy as a reverse proxy and load balancer

Sesame Overview Sesame is an Ingress controller for Kubernetes that works by dep

Dec 28, 2021

Substation is a cloud native toolkit for building modular ingest, transform, and load (ITL) data pipelines

Substation Substation is a cloud native data pipeline toolkit. What is Substation? Substation is a modular ingest, transform, load (ITL) application f

Dec 30, 2022

HTTP load generator, ApacheBench (ab) replacement, formerly known as rakyll/boom

HTTP load generator, ApacheBench (ab) replacement, formerly known as rakyll/boom

hey is a tiny program that sends some load to a web application. hey was originally called boom and was influenced from Tarek Ziade's tool at tarekzia

Jan 3, 2023

A Kubernetes Operator used for pre-scaling applications in anticipation of load

Pre-Scaling Kubernetes Operator Built out of necessity, the Operator helps pre-scale applications in anticipation of load. At its core, it manages a c

Oct 14, 2021

Build a retractable ECS load balance network through aliyun openapi.

ECSEquilizer 通过阿里云OpenAPI建立一个可伸缩的负载均衡网络调度器。 简介 为确保代理集群网络和计算能力可以通过ECS云服务动态伸缩,所以制定实现以下策略。 节点分为static和dynamic两种,static节点是通过配置文件(config.yaml)实现预设的,固定不变。 d

Jul 2, 2022

A minimal Go project with user authentication ready out of the box. All frontend assets should be less than 100 kB on every page load

Golang Base Project A minimal Golang project with user authentication ready out of the box. All frontend assets should be less than 100 kB on every pa

Jan 1, 2023
Comments
  • Trouble with Authentication Headers

    Trouble with Authentication Headers

    Hello,

    I'm trying to use Blast with a simple GET request that needs a Bearer token and I keep getting either errors (401) or JSON parsing errors.

    rate: 1
    workers: 1
    worker-type: "http"
    log: "out.log"
    headers: "[\"Authorization: Bearer ey--TQ\"]"
    payload-template:
      method: "GET"
      path: "/v1/object/abcdefg1234567"
    worker-template:
      print: true
      base: "https://sub.domain.com"
    

    I tried with dummy worker-type too, and I was not able to make it work. Using the same information I can do a cURL command successfully, so I know the URL + auth should work.

    Any ideas how I can achieve this?

Related tags
HTTP load testing tool and library. It's over 9000!
HTTP load testing tool and library. It's over 9000!

Vegeta Vegeta is a versatile HTTP load testing tool built out of a need to drill HTTP services with a constant request rate. It can be used both as a

Dec 30, 2022
k6 is a modern load testing tool for developers and testers in the DevOps era.
k6 is a modern load testing tool for developers and testers in the DevOps era.

k6 is a modern load testing tool, building on our years of experience in the load and performance testing industry. It provides a clean, approachable scripting API, local and cloud execution, and flexible configuration.

Jan 8, 2023
:rocket: Modern cross-platform HTTP load-testing tool written in Go
:rocket: Modern cross-platform HTTP load-testing tool written in Go

English | 中文 Cassowary is a modern HTTP/S, intuitive & cross-platform load testing tool built in Go for developers, testers and sysadmins. Cassowary d

Dec 29, 2022
Shared counter (with max limit) for k6 load testing tool

xk6-increment This is a k6 extension using the xk6 system. ❗ This is a proof of concept, isn't supported by the k6 team, and may break in the future.

Nov 30, 2021
Nomad is an easy-to-use, flexible, and performant workload orchestrator that can deploy a mix of microservice, batch, containerized, and non-containerized applications
Nomad is an easy-to-use, flexible, and performant workload orchestrator that can deploy a mix of microservice, batch, containerized, and non-containerized applications

Nomad is an easy-to-use, flexible, and performant workload orchestrator that can deploy a mix of microservice, batch, containerized, and non-containerized applications. Nomad is easy to operate and scale and has native Consul and Vault integrations.

Jan 5, 2023
Drone plugin for trigger Jenkins jobs.
Drone plugin for trigger Jenkins jobs.

drone-jenkins Drone plugin for trigger Jenkins jobs. Setup the Jenkins Server Setup the Jenkins server using the docker command: $ docker run \ --na

Sep 27, 2022
Terrform Provider for Managing Dkron Jobs

Terraform Provider Dkron Provider for managing https://dkron.io/ jobs. Usage examples terraform { required_providers { dkron = { version =

Oct 17, 2022
A batch scheduler of kubernetes for high performance workload, e.g. AI/ML, BigData, HPC
A batch scheduler of kubernetes for high performance workload, e.g. AI/ML, BigData, HPC

kube-batch kube-batch is a batch scheduler for Kubernetes, providing mechanisms for applications which would like to run batch jobs leveraging Kuberne

Jan 6, 2023
Repository belajar docker ALTA Immerseive Back-End Batch 4

Belajar Docker Repository belajar docker ALTA Immerseive Back-End Batch 4 Untuk materi ini teman-teman bisa download docker sesuai dengan OS masing-ma

Nov 12, 2021
Stuff to make standing up sigstore (esp. for testing) easier for e2e/integration testing.
Stuff to make standing up sigstore (esp. for testing) easier for e2e/integration testing.

sigstore-scaffolding This repository contains scaffolding to make standing up a full sigstore stack easier and automatable. Our focus is on running on

Dec 27, 2022