拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Hey HTTP压测工具命令行解析深度剖析:20个flag与headerSlice可重复-H参数设计指南

Hey HTTP压测工具命令行解析深度剖析:20个flag与headerSlice可重复-H参数设计指南

Hey HTTP压测工具命令行解析深度剖析:20个flag与headerSlice可重复-H参数设计指南

【免费下载链接】heyHTTP load generator, ApacheBench (ab) replacement项目地址: https://gitcode.com/GitHub_Trending/he/hey

🚀hey是一个轻量级的HTTP 压测工具(ApacheBench 的现代替代品),单文件即可完成数千并发请求。本文带你深度剖析 hey 的命令行参数解析设计:20 个 flag 如何定义、headerSlice自定义类型如何让-H参数支持可重复传入,以及正则表达式在其中扮演的角色。

hey 是什么:一个极简 HTTP 负载生成器

hey 的核心职责只有一个:向 Web 应用发送指定数量的请求,并输出响应时间的统计报告。相比ab,它:

  • 基于Go 语言编写,天然高并发,单二进制无依赖
  • 支持HTTP/2(-h2参数一键开启)
  • 输出更友好,支持 CSV 格式导出(-o csv)

想从源码开始体验,克隆仓库即可构建:

git clone https://gitcode.com/GitHub_Trending/he/hey

整个命令行层的核心代码集中在 hey.go 一个文件中,不到 300 行,是学习 CLI 参数设计的绝佳样本。

20个flag参数速查表:hey 压测参数一览

所有 flag 在 hey.go 的var块中集中声明,配合flag.String、flag.Int、flag.Duration等标准库函数注册。按功能可分为五组:

1️⃣ 请求量与控制类

参数类型默认值说明
-nint200总请求数
-cint50并发 worker 数
-qfloat640每个 worker 的 QPS 限流
-zduration0压测时长(如10s、3m),指定后忽略-n
-tint20单请求超时(秒),0表示不限

2️⃣ 请求内容与方法类

参数说明
-mHTTP 方法:GET / POST / PUT / DELETE / HEAD / OPTIONS
-d请求体内容
-D从文件读取请求体
-TContent-Type,默认text/html
-AAccept 头
-U自定义 User-Agent
-aBasic 认证,格式用户名:密码

3️⃣ 头信息类

  • -H:自定义 HTTP 头,可重复指定(本文重点,见下文)
  • -host:覆盖 HTTP Host 头,虚拟主机场景必备

4️⃣ 网络行为类

  • -x:HTTP 代理地址(host:port)
  • -h2:启用 HTTP/2
  • -disable-compression/-disable-keepalive/-disable-redirects:三个布尔开关,分别关闭压缩、连接复用与自动跟随重定向——压测时常用它们隔离变量,得到"纯净"的网络数据

5️⃣ 运行环境类

  • -o:输出类型,目前支持csv
  • -cpus:限制 CPU 核心数,默认取当前机器核数(hey.go 中通过runtime.GOMAXPROCS(-1)获取)

完整的参数说明文案定义在 hey.go 的usage常量里,hey -h时打印到标准错误流。

核心设计:可重复的 -H 参数与 headerSlice

很多工具的自定义头只能用逗号或分号拼接成一个字符串,用户还得自己写分割逻辑。hey 的做法更优雅:注册一个可重复的 flag。

var hs headerSlice flag.Var(&hs, "H", "")

就这两行(hey.go)。关键在于flag.Var:它接受任何实现了flag.Value接口的类型,之后每出现一次-H,就会调用一次Set方法。

headerSlice:仅 10 行的接口实现

headerSlice的定义在 hey.go:

type headerSlice []string func (h *headerSlice) String() string { return fmt.Sprintf("%s", *h) } func (h *headerSlice) Set(value string) error { *h = append(*h, value) return nil }
  • String():打印 flag 默认值时调用,返回当前切片内容
  • Set(value):每传入一个-H就append一次——这就是"可重复参数"的本质:接口 + 累积切片

于是用户可以自然地写成:

hey -H "Accept: application/json" \ -H "Authorization: Bearer token" \ https://example.com

正则校验:防御性解析

收集到原始字符串后,hey 在 hey.go 逐个用正则校验格式:

headerRegexp = `^([\w-]+):\s*(.+)`

这个正则要求必须是合法的名字: 值形式,解析失败就打印用法并退出(usageAndExit)。配套还有 Basic 认证的正则^(.+):([^\s].+)(hey.go)。

💡 值得注意:小写的-h曾是旧版自定义头参数,现在已被废弃。如果你还在用-h,程序会直接提示"Flag '-h' is deprecated, please use '-H' instead"(hey.go)。小写单字母让位给标准的帮助参数,大写-H承担业务功能——这是参数命名演进的经典案例。

参数校验与执行流程:从 flag 到 Work 结构体

参数注册之后,main()的执行流程(hey.go)可以概括为四步:

1. 互斥校验:-z指定时长后,请求数直接设为math.MaxInt32(无限);否则校验-n >= -c > 0,不满足立即退出。这种"参数间约束前置校验"避免了跑到一半才报错。

2. 组装请求头:先Content-Type,再叠加所有-H,然后Accept、Basic Auth;User-Agent 最后统一追加hey/0.0.1后缀,保证来源可追踪(hey.go)。

3. 构建请求:http.NewRequest创建请求,读取-D文件体,设置ContentLength与req.Host。

4. 交给 requester 包:所有 flag 最终映射进 requester.Work 结构体的字段——N、C、QPS、Timeout、H2、ProxyAddr等一一对应,再调用w.Run()启动 worker 池。QPS 限流则由time.Ticker精确按1e6/QPS微秒间隔放行(requester/requester.go)。

整个设计呈现出清晰的单向数据流:命令行字符串 → 校验 → 结构化配置 → 执行引擎,flag 包本身零业务逻辑。

典型压测命令示例

结合上面的参数,几组高频用法:

# 1000 请求、100 并发 hey -n 1000 -c 100 https://example.com # 持续压测 30 秒(-z 优先于 -n) hey -z 30s https://example.com # 每 worker 限流 10 QPS hey -q 10 -c 5 -z 30s https://example.com # POST 请求 + 自定义头 + HTTP/2 hey -m POST -d "a=1&b=2" \ -H "Content-Type: application/json" \ -h2 https://example.com

完整示例参考 README.md。

总结

hey 的命令行设计浓缩了三个可复用的模式:

  1. 集中声明:所有 flag 在一个var块,配合集中式usage文案,可读性极佳
  2. 可重复参数:flag.Var+ 自定义flag.Value类型(headerSlice),10 行代码实现优雅的多值采集
  3. 前置校验:参数间约束(-nvs-c、-z覆盖-n)在启动前一次性检查完毕

这套"字符串 → 结构化配置 → 执行"的单向数据流,几乎可以原样套用到你正在写的任何 Go CLI 工具中。

【免费下载链接】heyHTTP load generator, ApacheBench (ab) replacement项目地址: https://gitcode.com/GitHub_Trending/he/hey

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

返回列表