编程 go-stress:用 CLI 跑 HTTP/gRPC/WebSocket 压测,支持分布式与 60+ 变量函数

2026-09-16 00:03:59

go-stress:用 CLI 跑 HTTP/gRPC/WebSocket 压测,支持分布式与 60+ 变量函数

项目地址:https://github.com/kamalyes/go-stress,采用 MIT 许可证。

这是一个 Go 写的命令行压测工具,支持 HTTP/1.1、HTTP/2、gRPC、WebSocket 四种协议。除了单机压测,它还带了一套 Master/Slave 的分布式执行模型,以及一份可以直接上手用的参数化变量系统。配置来源有三种:命令行参数、YAML/JSON 配置文件、curl 文件转换。

架构分层

README 把内部结构拆成几块:

  • 压测引擎:Executor 编排器 / Scheduler 调度器 / WorkerPool / ClientPool
  • 中间件链:Breaker 熔断器 / Retry 重试器 / Verify 验证器 / Client 请求客户端
  • 协议支持:HTTP/1.1 & HTTP/2 / gRPC / WebSocket
  • 存储系统:Memory 内存存储 / SQLite 持久化 / Statistics 统计分析
  • 报告系统:Realtime 实时监控 / HTML 静态报告

请求会依次穿过中间件链再落到具体协议的客户端上,熔断、重试、响应验证都是链上可插拔的一环,开关放在配置文件的 advanced 段里。

安装与快速开始

# 安装
git clone https://github.com/kamalyes/go-stress.git
cd go-stress
go build -o go-stress .

# 简单压测
./go-stress -url https://api.example.com -c 10 -n 100

# 查看帮助
./go-stress help                # 完整帮助
./go-stress variables           # 查看所有变量函数
./go-stress examples            # 查看详细示例

入门教程见 docs/GETTING_STARTED.md

参数化请求:60+ 变量函数

变量用 {{...}} 包裹,在请求时求值,所以每个请求可以带不同的 ID、邮箱、时间戳:

# 每个请求自动生成唯一数据
./go-stress -url https://api.example.com/users \
  -method POST \
  -H "Content-Type: application/json" \
  -H "X-Request-ID: {{randomUUID}}" \
  -data '{
    "id": {{seq}},
    "email": "{{randomEmail}}",
    "phone": "{{randomPhone}}",
    "timestamp": {{unix}},
    "token": "{{md5 (print (seq) (timestamp))}}"
  }' \
  -c 100 -n 10000

函数支持嵌套调用,上面 md5 (print (seq) (timestamp)) 就是把序号和时间戳拼起来再取摘要。完整函数列表跑 ./go-stress variables 看,文档在 docs/VARIABLES.md

配置文件:复杂场景用 YAML 而不是长命令行

protocol: http
url: https://api.example.com/users
method: POST
concurrency: 100
requests: 50000
timeout: 10s

headers:
  Content-Type: application/json
  Authorization: "Bearer {{env \"API_TOKEN\"}}"
  X-Trace-ID: "{{md5 (print (seq) (timestamp))}}"

body: |
  {
    "id": {{seq}},
    "username": "user_{{randomString 8}}",
    "email": "{{randomEmail}}",
    "age": {{randomInt 18 65}},
    "created_at": "{{date \"2006-01-02 15:04:05\"}}"
  }

advanced:
  enable_breaker: true      # 熔断保护
  enable_retry: true        # 失败重试
  ramp_up: 30s             # 30秒内平滑启动

storage:
  mode: sqlite             # 持久化存储

realtime:
  enabled: true
  port: 8088

几个值得注意的点:

  • {{env "API_TOKEN"}} 可以读环境变量,凭据不用写死在文件里。
  • ramp_up: 30s 让并发在 30 秒内平滑爬升,避免起压瞬间打崩目标服务。
  • storage.mode 可选内存或 SQLite。内存模式快,SQLite 会把数据落盘,支持节点/任务级别的数据隔离,适合分布式场景下各 Slave 各自留存明细。
  • 断点:enable_breakerenable_retry 只是开关,具体阈值与重试次数的默认值需自行验证。

配置项完整说明在 docs/CONFIG_FILE.md,命令行参数见 docs/CLI_REFERENCE.md

WebSocket 压测

仓库里自带一个测试服务器,方便先跑通链路:

# 1. 启动测试服务器(内置 WebSocket 服务)
cd testserver
go run test_server.go
# 提供 3 个端点:
#   ws://localhost:3000/ws        (通用服务: ping/echo/info)
#   ws://localhost:3000/ws/echo   (回声服务器)
#   ws://localhost:3000/ws/chat   (聊天室模拟)

# 2. 运行压测 - 命令行方式
./go-stress -protocol websocket \
  -url ws://localhost:3000/ws \
  -body '{"action":"ping","message_id":1}' \
  -c 50 -n 1000

# 3. 配置文件方式(推荐)
./go-stress -config testserver/websocket-quick.yaml   # 快速测试 (5并发 20请求)
./go-stress -config testserver/websocket-test.yaml    # 通用服务 (10并发 100请求)
./go-stress -config testserver/websocket-echo.yaml    # 回声服务 (20并发 500请求)
./go-stress -config testserver/websocket-chat.yaml    # 聊天室压测 (50并发 1000请求)

# 一键测试脚本
.\test-websocket.ps1  # 自动启动服务器并运行压测

websocket-test.yaml 里可以在 body 中继续用变量:

protocol: websocket
url: ws://localhost:3000/ws
method: POST
concurrency: 10
requests: 100
timeout: 10s

body: |
  {
    "action": "echo",
    "message_id": {{seq}},
    "data": {
      "content": "测试消息 {{seq}}",
      "user_id": "user_{{randomInt 1000 9999}}",
      "timestamp": {{unix}}
    }
  }

advanced:
  enable_retry: true
  max_retry: 2
  ramp_up: 5s

realtime:
  enabled: true
  port: 8088

实时监控与报告

./go-stress -config config.yaml
# 自动打开浏览器 http://localhost:8088 查看实时数据
# 测试完成后生成 HTML 报告

实时页面跑在 realtime.port 指定的端口,压测结束后输出静态 HTML 报告。存储与报告的细节见 docs/STORAGE_REPORT.md

分布式压测:Master / Slave

# 1. 启动 Master 节点 - 协调和收集结果
./go-stress -mode master -grpc-port 9090 -http-port 8080

# 2. 启动 Slave 节点 - 在不同机器/区域运行
# 北京机房
./go-stress -mode slave -master master-ip:9090 -region beijing -slave-id slave-bj-1 -realtime-port 8088

# 上海机房
./go-stress -mode slave -master master-ip:9090 -region shanghai -slave-id slave-sh-1 -realtime-port 8089

# 3. 访问管理界面创建和启动任务
# http://master-ip:8080
#   - 创建任务(上传配置文件或在线编辑 YAML)
#   - 启动任务,支持 3 种 Slave 选择策略:
#     · 全部节点(默认)
#     · 指定节点(勾选特定 Slave)
#     · 按区域选择(如 beijing, shanghai)
#   - 查看实时执行情况(支持跨 Slave 数据查询)
#   - 任务失败/完成后可一键重试

工作流程是:创建任务(状态 pending)→ 启动任务并选择 Slave 策略(all/specific/region)→ 所有选定 Slave 并行执行 → 查看结果(实时监控 + 每个 Slave 独立报告)→ 任务重试时自动创建新任务副本,保留原配置。

Slave 通过 -region-slave-id 打标签,Master 侧就能按区域或按节点挑机器,跨机房压测时按地理位置分流比较直观。本地起一套 1 Master + 3 Slaves 可以用 .\test-distributed.ps1。完整说明见 docs/DISTRIBUTED_MODE.md

边界

  • 它是一个 CLI 驱动的压测工具,不是全链路压测平台:流量注入、结果呈现、任务重试都在这个工具的范围内,上下游依赖的链路治理不在其中。
  • 报告形式是实时页面加静态 HTML 文件,没有提到内置的 SLO 校验或 CI 断言能力,也没看到可以把压测结果接进流水线做失败判定的配置。如果要在 CI 里卡口,需要自己在 HTML/存储数据之外做一层解析。
  • gRPC 协议的支持范围(是否支持流式、是否需要 proto 文件)README 未展开,需自行验证。

仓库里还有 docs/CLI_REFERENCE.mddocs/CONFIG_FILE.mddocs/DISTRIBUTED_MODE.mddocs/VARIABLES.mddocs/STORAGE_REPORT.mddocs/GETTING_STARTED.md 几份文档,命令和配置项以这几份为准。

ramp_up 的时候记得它和 concurrency 是配合关系,爬升太慢会让统计窗口里的曲线看起来比实际服务能力平坦。

复制全文 生成海报 性能测试 压测 Go gRPC WebSocket CLI

推荐文章

程序员茄子在线接单