Hey压测HTTPS服务:TLS握手开销对延迟的影响及3种快速排除方法
【免费下载链接】heyHTTP load generator, ApacheBench (ab) replacement项目地址: https://gitcode.com/GitHub_Trending/he/hey
hey 是一款轻量级 HTTP 压测工具(ApacheBenchab的现代替代品),原生支持 HTTPS 与 HTTP/2。本文面向新手,讲清楚 hey 压测 HTTPS 服务时,TLS 握手开销如何体现在延迟指标里,以及如何用-disable-keepalive对比法快速量化并排除它对压测结果的影响。
为什么 HTTPS 压测的延迟总是比 HTTP 偏高?
🔐 每建立一条新的 HTTPS 连接,客户端和服务端都要先完成一次TLS 握手:
- TCP 三次握手(1 个 RTT)
- TLS 握手:TLS 1.2 通常需要 2 个 RTT,TLS 1.3 缩短到 1 个 RTT
- 之后才能真正发送 HTTP 请求
也就是说,一条"冷"连接的延迟天然比复用中的连接多出 1~2 个网络往返时间。同机房压测时一次握手大约 2~5ms,跨地域压测则可能到 30~80ms——如果每个请求都新建连接,这部分开销会直接叠加进你的平均延迟。
hey 的延迟分阶段指标:看懂 "DNS+dialup"
hey 用httptrace给每个请求做分阶段埋点(见 requester/requester.go),最终报告里包含 5 个阶段的平均值、最快值和最慢值:
| 阶段指标 | 含义 | 是否包含 TLS 握手 |
|---|---|---|
| DNS+dialup | DNS 解析 + TCP 建连 + TLS 握手(仅新连接) | ✅ 核心指标 |
| DNS-lookup | 仅 DNS 解析耗时 | ❌ |
| req write | 写完整请求的耗时 | ❌ |
| resp wait | 从发完请求到收到首字节的等待 | ❌(服务端响应时间) |
| resp read | 读完响应体的耗时 | ❌ |
默认报告模板定义在 requester/print.go。这里有一个新手最容易踩的坑:DNS+dialup只在连接未被复用时才被计时(requester/requester.go 中if !connInfo.Reused的判断)。hey 默认开启 keep-alive,连接会被反复复用,所以大多数请求的握手开销被"摊销"掉了,DNS+dialup平均值会显得很小——但这不代表握手不存在,只是没被逐次计入。
另外两点值得了解(见 requester/requester.go):
- hey 默认设置
InsecureSkipVerify: true,跳过 TLS 证书校验——压测时不会因自签证书报错,但 hey 的结果不能用于验证证书有效性; - 每主机的空闲连接池上限是
min(并发数, 500),并发-c超过 500 后会有连接频繁新建,额外触发握手。
3 条命令测出 TLS 握手开销(对比法)
💡 核心思路:其他条件完全一致,只切换"是否复用连接",两组DNS+dialup平均值的差,就近似等于单次 TLS+TCP 握手开销。
第 1 步:默认 keep-alive 压测(握手被摊销,代表真实用户场景)
hey -n 1000 -c 50 https://api.example.com第 2 步:加-disable-keepalive,每个请求都新建连接(完整暴露握手开销)
hey -n 1000 -c 50 -disable-keepalive https://api.example.com该参数的说明见 hey.go:禁用 keep-alive 后,不同请求之间不再复用 TCP 连接。
第 3 步:对比两组的 DNS+dialup 平均值,差值 ≈ 一次握手耗时
下面是一份示例输出(本地测试环境的典型量级,供参考):
| 指标 | keep-alive(默认) | -disable-keepalive | 差值 |
|---|---|---|---|
| DNS+dialup 平均 | 0.0002s | 0.0031s | ≈ 3ms / 次握手 |
| resp wait 平均 | 0.0048s | 0.0052s | 基本不变 |
可以看出:关闭复用后resp wait(服务端响应时间)几乎没变,涨的全是建连阶段——这就是 TLS 握手开销的"指纹"。
如需逐请求数据做进一步分析,用-o csv导出(字段说明见 requester/print.go):
hey -n 1000 -c 50 -z 30s -o csv -disable-keepalive https://api.example.com > tls_off.csvCSV 第 2 列DNS+dialup就是每次请求的连接建立耗时,可以自行统计分位数。
4 种降低 TLS 握手对延迟影响的方法
- ✅ 保持默认 keep-alive,让连接复用摊销握手成本。压测时不要随手加
-disable-keepalive,它只用于量化握手开销本身。 - ⚡ 用
-h2启用 HTTP/2 多路复用。一条 TLS 连接上可以跑多个并发流,握手次数从"每连接 1 次"降为接近"每 worker 1 次":hey -h2 -n 1000 -c 50 https://api.example.com - 📊 用
-z定时压测,让请求量足够大。例如-z 30s持续压测,握手只发生在起步阶段,占比自然摊薄;同时对比实验要固定-c与压测时长,保证两组可比。 - 🌐 缩短握手 RTT。把压测机部署到与目标同机房(跨地域 RTT 会线性放大握手成本);服务端升级到TLS 1.3(1-RTT 握手),并确保持有足够空闲连接池(
-c ≤ 500时每个 worker 可稳定持有空闲连接)。
安装 hey 与延伸阅读
通过 git 克隆源码构建:
git clone https://gitcode.com/GitHub_Trending/he/hey安装与构建方式详见 README.md 和 Makefile。本文涉及的核心文件:
- 命令行参数定义(
-disable-keepalive、-h2、-o csv等):hey.go - TLS 配置、连接池与 HTTP/2 开关:requester/requester.go
- 分阶段计时埋点逻辑:requester/requester.go
- 默认报告模板与 CSV 字段:requester/print.go
- 更多命令示例:README.md
掌握"DNS+dialup 对比法"后,你再用 hey 压测 HTTPS 服务时,就能一眼分清:慢在握手,还是慢在服务本身。
【免费下载链接】heyHTTP load generator, ApacheBench (ab) replacement项目地址: https://gitcode.com/GitHub_Trending/he/hey
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考