← 返回工具列表

y-http-bench

纯标准库、零依赖的 HTTP 压测命令行工具

  • 语言: Go 1.21+
  • 许可证: MIT
  • 平台: 15 个平台(Windows / Linux / macOS / FreeBSD)

技术栈

  • Go(纯标准库)
  • 单文件
  • 交叉编译
  • CLI

概览

y-http-bench 是一个用 Go 纯标准库写的 HTTP 压测(benchmark)工具:单文件、零依赖、开箱即用。编译出来就是一个可执行文件,不需要装任何运行时,也没有第三方库。

它面向的是「快速知道一个接口能扛多少」这个场景 —— 固定请求数、固定时长、或固定 QPS 三种压测方式任选,结束后直接给出延迟分位数报告。

快速开始

# 固定请求数:20000 次请求,100 并发
y-http-bench -url https://example.com -c 100 -n 20000

# 固定时长:50 并发压 30 秒
y-http-bench -url https://example.com -c 50 -d 30s

# 限速:稳定 1000 QPS 打 1 分钟
y-http-bench -url https://api.test/users -c 50 -d 1m -qps 1000

# POST 接口:自定义请求头 + 请求体
y-http-bench -url https://api.test/login -m POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer xxx" \
  -body '{"user":"tom","pwd":"123"}' -c 20 -n 5000

# 从文件读请求体 + 导出原始延迟数据用于画图
y-http-bench -url https://api.test/order -m POST \
  -body-file ./payload.json -c 30 -d 20s -dump-latency latency.csv

-n 和 -d 至少要指定一个(否则测试不会结束);两者同时给定时,先到达的条件触发结束。运行中按 Ctrl+C 会停止压测,并基于已采集的样本照常输出报告。

参数

参数 默认值 说明
-url 无(必填) 目标 URL
-m GET HTTP 方法
-c 10 并发数
-n 0 总请求数,0 表示不限(配合 -d)
-d 0 压测时长,如 10s / 2m,0 表示不限(配合 -n)
-qps 0 全局限速(请求/秒),0 表示不限速
-timeout 10s 单次请求超时
-H 无 自定义请求头,可重复传入
-body 空 请求体字符串
-body-file 空 从文件读取请求体
-keepalive true 是否复用连接,置为 false 可模拟短连接(每次握手)
-insecure false 跳过 TLS 证书校验(自签证书场景)
-dump-latency 空 把每次请求延迟流式导出为 CSV(列:latency_ms,status,bytes,error),不占额外内存
-v false 打印全部错误分类(默认最多显示 5 类)

输出说明

压测过程中每 500ms 刷新一行实时进度(耗时 / 已完成 / 实时 QPS / 失败数);结束后输出报告:

  • 概览:总请求数、失败数、成功率、平均 QPS、吞吐量(设了 -qps 时额外显示目标 QPS 与速率达成率)
  • 延迟分布:Min / Avg / P50 / P90 / P95 / P99 / P99.9 / Max(毫秒,读取完响应体为止)
  • 状态码分布
  • 错误分布(网络层错误按类型聚合)

延迟口径:只统计拿到响应的请求(含 4xx/5xx),网络层错误只计入失败数与错误分布;设了 -qps 时,计时起点是请求的「理想发出时刻」,排队等待时间也算进延迟。

实现要点

  • 限速器不用 time.Ticker:Windows 上 ticker 最小间隔受系统定时器精度限制(约 15.6ms),会把吞吐死死卡在 60~90 req/s(实测设定 5000 只跑出 88)。这里改用「绝对时间表」调度:第 n 个请求的理想发出时刻 = start + n×interval,只依赖 time.Now() 计算等待时间。实测 200 / 1000 / 5000 三档分别跑出 188 / 985 / 4982 req/s
  • 延迟从「理想发出时刻」起算(coordinated omission 修正):被限速器推迟、或上一批请求把 worker 拖慢所积累的排队时间都会计入延迟,否则高负载下 P99 会明显偏乐观(wrk2 的 fixed-rate 模式同理)
  • 延迟统计用直方图,不保留全量样本:对数线性分桶,1024 桶/量级共 32 个量级(固定 256KB,与请求量无关),相对误差上限约 0.1%;分位数取桶中点并夹到 [Min, Max] 之间
  • -dump-latency 流式落盘:合并样本时顺手写进 bufio.Writer,不把全量样本留在内存里
  • 显式开启 HTTP/2:手写 http.Transport 时 Go 不会自动启用 HTTP/2,需要 ForceAttemptHTTP2: true
  • 表头按显示宽度对齐:中文在终端占 2 个显示列,用 padRight / displayWidth 自己补空格,避免中文表头把表格挤错位

已知局限

  1. 仍是闭环(closed-loop)压测:每个 worker 必须等上一次响应读完才发下一次。设了 -qps 时排队时间会被补进延迟,但真要「按固定速率发出、不被服务端拖慢」需要开环模型
  2. 单机单进程,没有多 URL / 多阶段场景、爬坡、think time、断言与 SLA 阈值判定,也不支持分布式
  3. 每请求一次分配(Request.Clone + 新建 Body reader),极限吞吐下不如 wrk 这类 epoll + 复用缓冲的实现
  4. 客户端侧指标没有拆分统计:连接复用次数、DNS / TCP / TLS 各阶段耗时都没有单独列出

压测注意事项

  1. 压的是被测服务,不是本机网络:尽量在与被测机同机房/内网的中立机器上跑
  2. 先区分瓶颈在哪一方 —— 观察被测机 CPU、GC、连接池是否打满
  3. 关注 P99 / P99.9 而不是平均值,平均值容易被大量快请求掩盖长尾
  4. Windows 下临时端口回收较慢,短连接高压场景可能出现 connectex 拒绝,属被测端或系统限制

许可

MIT · 源码:GitHub · 发布页:Releases

最近更新