golang高性能API负载测试与批量任务处理插件Blast的使用

Golang高性能API负载测试与批量任务处理插件Blast的使用

Blast简介

Blast是一个高性能的Golang工具,主要用于:

  1. 以固定速率发送API请求
  2. 并发工作者数量可配置
  3. 执行期间可交互式调整速率
  4. 协议无关,轻松添加新的工作者类型
  5. 负载测试:可以向API请求添加随机数据
  6. 批量任务处理:可以从本地文件或GCS存储桶加载CSV数据,并跳过先前运行中的成功项

Build Status Go Report Card codecov

安装

Mac

brew tap dave/blast
brew install blast

Linux

查看发布页面获取安装包

从源码安装

go get -u github.com/dave/blast

使用示例

使用dummy工作者以20,000请求/秒的速度发送请求

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

使用http工作者以1请求/秒的速度请求Google主页

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

状态监控

Blast每十秒打印一次摘要。运行时可以:

  • 按Enter键查看最新状态
  • 输入数字调整发送速率

示例输出:

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?

配置

Blast可以通过配置文件、命令行标志或环境变量进行配置。--config标志指定要加载的配置文件,可以是jsonyamltoml或任何Viper支持的格式。

环境变量和命令行标志会覆盖配置文件选项。环境变量需大写并加上"BLAST"前缀,例如BLAST_PAYLOAD_TEMPLATE

模板

payload-templateworker-template选项使用Go的text/template系统渲染。变量形式如{{ .name }}{{ "name" }}会被数据替换。

还提供了一些简单的函数来注入随机数据,这对负载测试场景很有用:

  • {{ rand_int -5 5 }} - -5到5之间的随机整数
  • {{ rand_float -5 5 }} - -5到5之间的随机浮点数
  • {{ rand_string 10 }} - 长度为10的随机字符串

工作者

Worker是一个接口,允许Blast轻松扩展以支持任何协议。Worker还可以选择性地实现Starter和Stopper接口来提供初始化或终结逻辑。

完整示例

负载测试配置示例

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"

批量API任务配置示例

# 数据通常是本地CSV文件或GCS存储桶中的对象
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"

代码控制示例

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

待办事项

  • [ ] 根据延迟自动调整速率?PID控制器?
  • [ ] 仅使用文件的一部分:i部分中的j部分

更多关于golang高性能API负载测试与批量任务处理插件Blast的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang高性能API负载测试与批量任务处理插件Blast的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang高性能API负载测试与批量任务处理插件Blast使用指南

Blast是一个用Go语言编写的高性能HTTP负载测试工具和批量任务处理框架,特别适合API性能测试和大规模任务处理场景。

Blast核心特性

  1. 高性能:基于Go协程实现高并发
  2. 灵活配置:支持自定义请求参数、头信息和请求体
  3. 结果统计:提供详细的请求统计和性能指标
  4. 批量处理:支持任务队列和批量处理模式
  5. 扩展性强:可通过插件机制扩展功能

安装Blast

go get -u github.com/dave/blast

基础使用示例

1. 简单负载测试

package main

import (
	"github.com/dave/blast"
	"log"
	"time"
)

func main() {
	// 创建Blast实例
	b := blast.New()

	// 配置测试参数
	b.
		URL("https://api.example.com/users").
		Method("GET").
		Concurrency(100).          // 并发数
		Requests(1000).            // 总请求数
		Timeout(10 * time.Second). // 超时时间
		Header("Authorization", "Bearer token123")

	// 运行测试
	result, err := b.Run()
	if err != nil {
		log.Fatal(err)
	}

	// 打印结果
	log.Printf("Completed %d requests in %v", result.Requests, result.Duration)
	log.Printf("Success rate: %.2f%%", result.SuccessRate()*100)
	log.Printf("Requests per second: %.2f", result.RequestsPerSecond())
	log.Printf("Average latency: %v", result.AverageLatency())
}

2. 带请求体的POST测试

func postTest() {
	b := blast.New().
		URL("https://api.example.com/users").
		Method("POST").
		Body([]byte(`{"name":"test","email":"test@example.com"}`)).
		Header("Content-Type", "application/json").
		Concurrency(50).
		Requests(500)

	result, err := b.Run()
	if err != nil {
		log.Fatal(err)
	}

	// 输出详细统计
	log.Println(result.String())
}

高级功能

1. 批量任务处理

func batchProcessing() {
	// 准备任务数据
	userIDs := []string{"1", "2", "3", "4", "5"}

	// 创建批量处理器
	processor := blast.NewBatchProcessor().
		Concurrency(10). // 并发处理数
		Timeout(5 * time.Second)

	// 添加处理函数
	processor.Handle(func(id interface{}) (interface{}, error) {
		userID := id.(string)
		// 这里执行实际的任务处理逻辑
		resp, err := http.Get(fmt.Sprintf("https://api.example.com/users/%s", userID))
		if err != nil {
			return nil, err
		}
		defer resp.Body.Close()
		// 返回处理结果
		return resp.Status, nil
	})

	// 提交任务并获取结果
	results := processor.Process(userIDs)

	// 处理结果
	for _, result := range results {
		if result.Error != nil {
			log.Printf("Error processing task: %v", result.Error)
		} else {
			log.Printf("Task result: %v", result.Value)
		}
	}
}

2. 自定义请求生成器

func customRequestGenerator() {
	b := blast.New().
		Concurrency(20).
		Requests(200).
		RequestGenerator(func() *blast.Request {
			// 动态生成请求
			userID := rand.Intn(1000)
			return &blast.Request{
				Method: "GET",
				URL:    fmt.Sprintf("https://api.example.com/users/%d", userID),
				Headers: map[string]string{
					"Authorization": "Bearer token123",
				},
			}
		})

	result, err := b.Run()
	if err != nil {
		log.Fatal(err)
	}

	// 输出百分位延迟
	log.Printf("50%% latency: %v", result.PercentileLatency(0.5))
	log.Printf("95%% latency: %v", result.PercentileLatency(0.95))
	log.Printf("99%% latency: %v", result.PercentileLatency(0.99))
}

性能优化建议

  1. 合理设置并发数:根据目标服务器性能和网络条件调整
  2. 使用连接池:Blast内部已经实现了HTTP连接复用
  3. 减少内存分配:重用请求对象和缓冲区
  4. 监控系统资源:避免测试客户端成为瓶颈
  5. 分布式测试:对于极高负载测试,考虑在多台机器上分布式运行

结果分析与可视化

Blast提供丰富的测试结果数据,可以集成到监控系统中:

func analyzeResults(result *blast.Result) {
	// 输出详细统计
	fmt.Println("=== 测试结果 ===")
	fmt.Printf("总请求数: %d\n", result.Requests)
	fmt.Printf("成功请求: %d\n", result.Success)
	fmt.Printf("失败请求: %d\n", result.Failures)
	fmt.Printf("总耗时: %v\n", result.Duration)
	fmt.Printf("QPS: %.2f\n", result.RequestsPerSecond())
	fmt.Printf("平均延迟: %v\n", result.AverageLatency())
	fmt.Printf("最大延迟: %v\n", result.MaxLatency)
	fmt.Printf("最小延迟: %v\n", result.MinLatency)
	
	// 可以导出为JSON用于可视化
	jsonData, _ := json.MarshalIndent(result, "", "  ")
	_ = os.WriteFile("test_result.json", jsonData, 0644)
}

Blast是一个强大而灵活的工具,通过合理配置可以满足从简单API测试到复杂批量任务处理的各种需求。其基于Go语言的特性使其在性能上具有明显优势,特别适合高并发场景下的性能测试和任务处理。

回到顶部