3. 压测工具选型:wrk、hey、vegeta、ghz(gRPC)、自研压测框架对比

在尾延迟诊断场景中,压测工具的选择直接影响测试结果的准确性和可复现性。不同的工具在并发模型、协议支持、统计输出、资源开销等方面存在显著差异。本章对主流压测工具进行系统性对比,帮助你在不同场景下做出合理选型。

3.1 工具概览与核心定位

以下表格从协议支持、并发模型、统计能力、适用场景四个维度对五类工具进行横向对比:

工具 协议支持 并发模型 延迟统计 典型场景
wrk HTTP/1.1, HTTPS 多线程 + epoll/kqueue 平均值、标准差、百分位 快速吞吐测试、短连接压测
hey HTTP/1.1, HTTPS goroutine + 连接池 平均值、百分位、直方图 简单功能验证、小规模压测
vegeta HTTP/1.1, HTTPS 固定速率 + 攻击器 百分位、延迟分布、实时报告 恒定速率压测、SLA验证
ghz gRPC (HTTP/2) goroutine + 流式连接 百分位、延迟分布、错误码 gRPC服务压测、流式接口
自研框架 任意协议 可定制 全量记录、自定义分位 复杂场景、协议定制、持续集成
选型建议: 如果仅需快速验证 HTTP 接口的吞吐能力,wrk 是最轻量的选择;若需要精确控制请求速率并输出百分位延迟,vegeta 更合适;gRPC 场景下 ghz 是事实标准;当需要模拟复杂业务逻辑或自定义协议时,自研框架是唯一选项。

3.2 工具深度对比

3.2.1 wrk:高性能 HTTP 压测标杆

wrk 使用 C 语言编写,基于多线程和 epoll/kqueue 事件驱动模型,能够在单机上产生极高的并发压力。其核心优势在于:

  • 极低资源开销: 单线程可管理数万个连接,适合大规模并发场景。
  • Lua 脚本扩展: 支持自定义请求构造、响应处理、延迟记录。
  • 实时统计输出: 测试过程中实时显示延迟平均值和标准差。

典型用法示例:

# 30秒压测,16个线程,100个连接
wrk -t16 -c100 -d30s --latency http://target:8080/api

# 使用Lua脚本自定义请求
wrk -t4 -c50 -d10s -s custom.lua http://target:8080/api
注意: wrk 默认使用 HTTP/1.1 长连接,且不支持 HTTP/2。在测试 gRPC 或 HTTP/2 服务时,wrk 无法直接使用。此外,wrk 的百分位统计仅输出 p50、p75、p90、p99,缺少 p999 和 p9999 等尾延迟关键指标。

3.2.2 hey:Go 生态的轻量压测工具

hey 由 Go 语言编写,利用 goroutine 实现并发,安装简单,适合快速验证。其特点包括:

  • 零依赖: 单二进制文件,无需安装运行时。
  • 内置直方图: 输出延迟分布直方图,便于直观观察延迟分布。
  • 支持自定义 Header 和 Body: 通过命令行参数灵活构造请求。

典型用法:

# 100个并发,总共发送1000个请求
hey -n 1000 -c 100 -h2 http://target:8080/api

# 输出详细延迟分布
hey -n 5000 -c 50 -o csv http://target:8080/api
对比要点: hey 的并发模型基于 goroutine,在极高并发(>10000)下性能不如 wrk 的 epoll 模型。但 hey 的安装便捷性和直方图输出使其在开发调试阶段非常实用。

3.2.3 vegeta:恒定速率压测与 SLA 验证

vegeta 的设计理念是“恒定攻击速率”,而非“最大并发”。它通过攻击器(attacker)以固定速率发送请求,适合模拟真实用户流量。核心特性:

  • 速率控制: 精确控制每秒请求数(RPS),支持线性/指数递增。
  • 实时报告: 支持终端实时显示延迟百分位和吞吐量。
  • 结果导出: 支持 JSON、CSV、直方图等多种输出格式。

典型用法:

# 以每秒500请求的速率压测30秒
echo "GET http://target:8080/api" | vegeta attack -rate=500 -duration=30s | vegeta report

# 输出百分位延迟报告
echo "GET http://target:8080/api" | vegeta attack -rate=1000 -duration=60s | vegeta report -type=text
尾延迟诊断优势: vegeta 的 report 命令默认输出 p50、p90、p95、p99,且支持通过 -percentiles 参数自定义分位点,非常适合尾延迟分析。

3.2.4 ghz:gRPC 压测专用工具

ghz 是专为 gRPC 服务设计的压测工具,支持一元调用、服务端流、客户端流和双向流四种模式。其关键能力:

  • Protobuf 原生支持: 直接读取 .proto 文件构造请求。
  • 流式压测: 支持 gRPC 流式接口的持续压测。
  • 元数据注入: 支持自定义 gRPC metadata 和超时设置。

典型用法:

# 一元调用压测,100个并发,持续30秒
ghz --insecure \
    --proto ./api.proto \
    --call mypackage.MyService.UnaryCall \
    -d '{"name": "test"}' \
    -c 100 -z 30s \
    target:50051

# 输出详细延迟分布
ghz --insecure \
    --proto ./api.proto \
    --call mypackage.MyService.UnaryCall \
    -d '{"name": "test"}' \
    -c 50 -n 10000 \
    --format=pretty \
    target:50051
注意: ghz 默认使用 HTTP/2 连接,且支持连接复用。在测试流式接口时,需注意并发数(-c)和连接数(-cpus)的合理配置,避免客户端成为瓶颈。

3.2.5 自研压测框架:应对复杂场景的终极方案

当现有工具无法满足以下需求时,自研压测框架成为必要选择:

  • 自定义协议: 如 WebSocket、MQTT、私有 TCP/UDP 协议。
  • 复杂业务逻辑: 需要模拟多步骤事务、条件分支、状态依赖。
  • 全量延迟记录: 需要记录每次请求的完整时间戳,用于离线分析。
  • 分布式压测: 需要多节点协同压测,汇总结果。

一个典型的 Go 自研压测框架结构如下:

// 核心压测引擎示例
type LoadTester struct {
    client    *http.Client
    rate      int           // 目标RPS
    duration  time.Duration // 压测时长
    results   chan *Result  // 结果通道
    stopCh    chan struct{} // 停止信号
}

func (lt *LoadTester) Run() {
    ticker := time.NewTicker(time.Second / time.Duration(lt.rate))
    defer ticker.Stop()

    for {
        select {
        case <-ticker.C:
            go lt.sendRequest()
        case <-lt.stopCh:
            return
        }
    }
}

func (lt *LoadTester) sendRequest() {
    start := time.Now()
    resp, err := lt.client.Get("http://target:8080/api")
    latency := time.Since(start)
    lt.results <- &Result{
        Latency: latency,
        Error:   err,
        Status:  resp.StatusCode,
    }
}
自研框架优势: 可以精确控制请求发送时机(如泊松分布)、记录每次请求的完整链路信息、支持动态调整压测参数、与 CI/CD 流水线深度集成。但代价是开发成本和维护成本较高。

3.3 工具选型决策流程

以下 SVG 流程图展示了在不同场景下的工具选型决策路径:

压测工具选型决策流程 压测需求 协议类型? gRPC ghz HTTP 压测模式? 最大并发 wrk 恒定速率 vegeta 快速验证 hey 需要定制协议/逻辑? 否 直接使用 是 自研框架

3.4 尾延迟诊断场景下的工具选择建议

针对尾延迟诊断这一核心目标,不同工具在延迟精度和统计能力上存在差异:

需求场景 推荐工具 关键配置 尾延迟指标
HTTP 服务尾延迟初筛 wrk + Lua 脚本 --latency 开启百分位输出 p99, p999
gRPC 服务尾延迟分析 ghz --format=pretty 输出详细分布 p99, p999, p9999
SLA 验证(固定速率) vegeta -rate 精确控制 RPS p95, p99, 最大延迟
全量延迟分布采集 自研框架 记录每次请求的纳秒级时间戳 任意分位点
CI/CD 集成压测 vegeta / 自研框架 输出 JSON 格式结果 p99 阈值断言
核心原则: 尾延迟诊断要求工具能够记录高精度(微秒级)的延迟数据,并支持输出 p999 甚至 p9999 级别的百分位。wrk 和 hey 默认不输出 p999,需要通过脚本或二次开发实现;vegeta 和 ghz 原生支持自定义分位点;自研框架则可以做到全量记录,无精度损失。

3.5 工具选型总结

以下 SVG 图展示了各工具在“易用性”与“灵活性”两个维度上的定位:

压测工具定位矩阵 灵活性(协议/逻辑定制能力) 易用性 低 中 高 低 中 高 wrk hey vegeta ghz 自研框架 选型建议 右上角:高灵活性,适合复杂场景 左下角:高易用性,适合快速验证