4. 压测工具选型与安装:benchmark 工具、ghz、自定义 Go 压测客户端、wrk2 对比

在 etcd 压测工程中,工具选型直接影响压测结果的可靠性与瓶颈定位效率。本章对四类主流压测工具进行横向对比,并给出安装与基本使用指引,帮助你在不同场景下选择最合适的工具。

选型原则: 压测工具的选择应基于测试目标——是验证 etcd 的极限吞吐、模拟真实业务负载,还是定位特定 API 的延迟瓶颈。没有万能工具,只有最匹配场景的方案。

4.1 工具全景对比

下表从协议支持、并发模型、指标输出、适用场景四个维度对 benchmark、ghz、自定义 Go 客户端、wrk2 进行对比:

工具 协议支持 并发模型 指标输出 核心适用场景
benchmark(etcd 官方) gRPC(etcd v3 API) 固定协程池 + 请求率控制 吞吐、延迟分位值、错误率 etcd 集群基准性能测试、版本对比
ghz gRPC(通用) 多 worker + 异步非阻塞 延迟分布、百分位、直方图 gRPC 微服务压测、自定义 protobuf 消息
自定义 Go 客户端 gRPC / HTTP(灵活) 完全可控(协程、限流、重试) 自定义 Prometheus 指标、日志 模拟真实业务模式、故障注入、长稳测试
wrk2 HTTP/1.1 多线程 + 事件循环(基于 redis/lua) 延迟分布、吞吐、尾部延迟 HTTP 网关层压测、延迟稳定性验证

4.2 工具详解与安装

4.2.1 etcd benchmark 工具

etcd 官方提供的 benchmark 工具是压测 etcd 的首选工具,直接调用 etcd v3 gRPC API,支持 put、range、delete、txn 等操作。它内置了请求率控制(--rate-limit)和并发数控制(--clients),输出结果包含吞吐量(QPS)和延迟分位值(P50/P90/P99/P99.9)。

安装方式:

# 方式一:从 etcd 源码编译
git clone https://github.com/etcd-io/etcd.git
cd etcd/tools/benchmark
go build -o benchmark .

# 方式二:使用预编译二进制(从 etcd 发布页下载)
wget https://github.com/etcd-io/etcd/releases/download/v3.5.15/etcd-v3.5.15-linux-amd64.tar.gz
tar -xzf etcd-v3.5.15-linux-amd64.tar.gz
cd etcd-v3.5.15-linux-amd64
./benchmark

基本使用示例:

# 对 3 节点 etcd 集群执行 put 压测,10 个客户端,总请求 10000,限速 1000 QPS
./benchmark put \
  --endpoints=10.0.0.1:2379,10.0.0.2:2379,10.0.0.3:2379 \
  --clients=10 \
  --total=10000 \
  --rate-limit=1000 \
  --key-size=8 \
  --val-size=256
关键参数说明: --rate-limit 控制每秒请求数,用于避免压垮集群;--clients 控制并发连接数,建议不超过 etcd 节点 CPU 核心数的 2 倍;--key-size 和 --val-size 模拟实际 key/value 大小。

4.2.2 ghz

ghz 是一个通用的 gRPC 压测工具,支持自定义 protobuf 消息、元数据、TLS 等。它采用多 worker 异步模型,能够生成详细的延迟分布报告,包括直方图和百分位图。对于 etcd 压测,ghz 可以模拟更复杂的 gRPC 调用模式。

安装方式:

# 方式一:Go 安装
go install github.com/bojand/ghz/cmd/ghz@latest

# 方式二:Docker
docker pull bojand/ghz:latest

# 方式三:预编译二进制(从 GitHub Releases 下载)
wget https://github.com/bojand/ghz/releases/download/v0.120.0/ghz-linux-x86_64.tar.gz
tar -xzf ghz-linux-x86_64.tar.gz
./ghz

基本使用示例:

# 使用 ghz 对 etcd 的 Range RPC 进行压测
ghz \
  --insecure \
  --proto=/path/to/etcd/api/etcdserverpb/rpc.proto \
  --call=etcdserverpb.KV.Range \
  -d '{"key":"dGVzdA=="}' \
  -c 10 \
  -n 10000 \
  --rps 1000 \
  10.0.0.1:2379
注意: ghz 需要 protobuf 定义文件(.proto)来序列化请求消息。etcd 的 proto 文件位于 etcd 源码的 api/etcdserverpb/ 目录下。如果 proto 文件依赖较多,建议使用 protoc 提前编译好依赖。

4.2.3 自定义 Go 压测客户端

当官方工具无法满足复杂压测场景时(如模拟事务、条件更新、watch 流、故障注入),自定义 Go 客户端是最灵活的选择。它直接使用 etcd clientv3 库,可以精确控制每个请求的构造、重试策略、超时设置,并输出自定义 Prometheus 指标。

最小化压测框架示例:

package main

import (
    "context"
    "fmt"
    "sync/atomic"
    "time"

    clientv3 "go.etcd.io/etcd/client/v3"
    "golang.org/x/time/rate"
)

func main() {
    cli, _ := clientv3.New(clientv3.Config{
        Endpoints:   []string{"10.0.0.1:2379"},
        DialTimeout: 5 * time.Second,
    })
    defer cli.Close()

    var success, failure int64
    limiter := rate.NewLimiter(rate.Limit(1000), 1) // 1000 QPS 限流

    for i := 0; i < 10000; i++ {
        limiter.Wait(context.Background())
        go func() {
            _, err := cli.Put(context.Background(), "key", "value")
            if err != nil {
                atomic.AddInt64(&failure, 1)
            } else {
                atomic.AddInt64(&success, 1)
            }
        }()
    }
    time.Sleep(5 * time.Second)
    fmt.Printf("Success: %d, Failure: %d\n", success, failure)
}

安装依赖:

go get go.etcd.io/etcd/client/v3
go get golang.org/x/time/rate
工程建议: 自定义客户端应内置 Prometheus 指标注册(如请求数、延迟直方图、错误率),方便与 Prometheus + Grafana 监控体系集成,实现压测过程中的实时瓶颈定位。

4.2.4 wrk2

wrk2 是 wrk 的增强版,专注于尾部延迟的精确测量。它通过恒定吞吐量模式(--rate)控制请求率,输出延迟分布(包括 P99.9、P99.99)。wrk2 仅支持 HTTP/1.1 协议,因此适用于 etcd 的 HTTP 网关层(如 etcd 的 HTTP API 或自定义代理)压测。

安装方式:

# 从源码编译
git clone https://github.com/giltene/wrk2.git
cd wrk2
make

# 编译后二进制位于 wrk2/wrk

基本使用示例:

# 对 etcd HTTP API 进行压测,12 个线程,400 个连接,持续 30 秒,限速 5000 QPS
./wrk -t12 -c400 -d30s --rate 5000 \
  http://10.0.0.1:2379/v3/kv/put \
  -s put.lua

Lua 脚本示例(put.lua):

wrk.method = "POST"
wrk.body = '{"key":"dGVzdA==","value":"dmFsdWU="}'
wrk.headers["Content-Type"] = "application/json"
限制说明: wrk2 无法直接调用 etcd gRPC API,只能压测 HTTP 网关层。对于 etcd v3 的 gRPC 原生接口,请使用 benchmark 或 ghz。wrk2 的优势在于尾部延迟的精确测量,适合验证网关层的延迟稳定性。

4.3 工具选型决策流程

下图展示了在不同压测目标下的工具选型决策路径:

压测工具选型决策流程 压测目标定义 协议类型? gRPC vs HTTP gRPC HTTP 场景复杂度? 标准 vs 自定义 benchmark ghz / 自定义Go wrk2 选型建议 • 基准性能测试 → benchmark(官方、标准、可靠) • 复杂 gRPC 场景 → ghz(灵活、支持自定义 proto) • 真实业务模拟 → 自定义 Go 客户端(完全可控) • HTTP 网关层压测 → wrk2(尾部延迟精确)

4.4 工具组合使用策略

在实际压测工程中,单一工具往往无法覆盖所有测试维度。推荐采用分层组合策略:

  • 第一层(基准层): 使用 benchmark 工具对 etcd 集群进行标准吞吐和延迟测试,建立基线指标。
  • 第二层(协议层): 使用 ghz 模拟更复杂的 gRPC 调用模式(如事务、watch),验证协议层性能。
  • 第三层(业务层): 使用自定义 Go 客户端模拟真实业务流量模式(如读写比例、key 分布、超时重试),并输出 Prometheus 指标。
  • 第四层(网关层): 使用 wrk2 对 HTTP 网关或代理进行尾部延迟验证,确保网关层不会成为瓶颈。
工程实践: 在 etcd 压测沙盘中,我们通常先使用 benchmark 快速定位集群的极限吞吐,然后使用自定义 Go 客户端模拟真实业务负载,最后使用 wrk2 验证网关层的延迟稳定性。这种分层组合能够全面覆盖从底层到上层的性能瓶颈。

4.5 安装验证与常见问题

安装完成后,建议执行以下验证步骤确保工具正常工作:

工具 验证命令 预期输出
benchmark ./benchmark --help 显示帮助信息,包含所有子命令和参数
ghz ghz --version 显示版本号(如 v0.120.0)
自定义 Go 客户端 go run main.go 编译通过并输出压测结果
wrk2 ./wrk --version 显示版本信息
常见问题:
  • benchmark 连接失败: 检查 --endpoints 地址是否正确,etcd 集群是否正常运行,防火墙是否放行 2379 端口。
  • ghz proto 依赖缺失: 确保 proto 文件路径正确,且所有依赖的 proto 文件(如 google/protobuf/any.proto)已下载到本地。
  • 自定义客户端限流不生效: 检查 rate.Limiter 的 Wait 调用是否在 goroutine 内部,避免并发竞争导致限流失效。
  • wrk2 报错 "Cannot assign requested address": 减少连接数(-c)或增加本地端口范围(sysctl -w net.ipv4.ip_local_port_range="1024 65535")。