Hey 压力测试工具完整使用指南
Hey(原名为 Boom)是用 Go 语言编写的现代化 HTTP 负载测试工具,性能比 Apache Bench 更好。
1. 安装 Hey
在 Windows 上安装
# 方法1:使用 Scoop
scoop install hey
# 方法2:下载二进制文件
# 访问:https://github.com/rakyll/hey/releases
# 下载 hey_windows_amd64.exe,重命名为 hey.exe,添加到 PATH
# 方法3:通过 Go 安装
go install github.com/rakyll/hey@latest
# 然后确保 GOPATH/bin 在 PATH 中
在 macOS 上安装
# 使用 Homebrew
brew install hey
# 或通过 Go
go install github.com/rakyll/hey@latest
在 Linux 上安装
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install hey
# 或通过 Go
go install github.com/rakyll/hey@latest
2. 基本用法
快速开始
# 基本 GET 请求测试
hey https://example.com
# 设置并发数和请求数
hey -n 1000 -c 50 https://example.com
基本参数
# 指定总请求数
hey -n 2000 https://api.example.com
# 指定并发数(同时进行的请求数)
hey -c 100 https://api.example.com
# 指定测试持续时间
hey -z 30s https://api.example.com # 30秒
hey -z 5m https://api.example.com # 5分钟
hey -z 2h https://api.example.com # 2小时
# 组合使用
hey -n 10000 -c 200 -z 1m https://api.example.com
3. 常用参数详解
负载参数
# 并发控制
-c 100 # 100个并发worker
-n 10000 # 总共10000个请求
-z 30s # 持续30秒
-q 100 # 限制每个worker每秒100个请求
# 如果同时指定-n和-z,以先达到的为准
hey -n 1000 -z 10s https://example.com
HTTP 方法控制
# 指定 HTTP 方法
-m GET # GET请求(默认)
-m POST # POST请求
-m PUT # PUT请求
-m DELETE # DELETE请求
-m PATCH # PATCH请求
hey -m POST https://api.example.com/users
请求头和内容
# 自定义请求头
-H "Content-Type: application/json"
-H "Authorization: Bearer token123"
-H "User-Agent: MyLoadTest/1.0"
# 多个请求头
hey -H "Accept: application/json" \
-H "X-API-Key: mykey" \
https://api.example.com/data
# POST 数据
-d '{"name":"John","age":30}'
-d "username=admin&password=123456"
# 从文件读取请求体
-D data.json
-D post_data.txt
# Content-Type
-T "application/json"
-T "application/x-www-form-urlencoded"
超时和重试
# 超时设置
-t 10 # 每个请求10秒超时
-t 0 # 无超时
# 禁用 keep-alive
-disable-keepalive
# 禁用压缩
-disable-compression
# 主机头覆盖
-host "api.example.com"
# 代理设置
-x http://proxy:8080
4. 实战示例
示例1:基本网站压力测试
# 测试网站首页
hey -z 30s -c 100 https://example.com
# 详细输出
hey -z 30s -c 100 -m GET -t 5 \
-H "Accept: text/html" \
https://example.com
示例2:REST API 测试
# GET 请求测试
hey -z 1m -c 50 -m GET \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." \
-H "Accept: application/json" \
https://api.example.com/users
# POST JSON 数据
hey -z 1m -c 20 -m POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer token123" \
-d '{"name":"test","email":"test@example.com"}' \
https://api.example.com/users
# PUT 请求
hey -n 1000 -c 10 -m PUT \
-H "Content-Type: application/json" \
-d '{"status":"active"}' \
https://api.example.com/users/123
示例3:登录接口测试
# 表单登录
hey -z 2m -c 20 -m POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=testuser&password=testpass" \
https://api.example.com/login
# JSON 登录
hey -z 2m -c 20 -m POST \
-H "Content-Type: application/json" \
-d '{"username":"test","password":"123456"}' \
https://api.example.com/auth/login
示例4:文件上传测试
# 使用 -D 从文件读取 multipart 数据
# 首先创建 multipart 数据文件
echo '--boundary
Content-Disposition: form-data; name="file"; filename="test.jpg"
Content-Type: image/jpeg
[文件内容,这里可以使用二进制]
--boundary--
' > upload_data.txt
# 然后测试
hey -z 1m -c 5 -m POST \
-H "Content-Type: multipart/form-data; boundary=boundary" \
-D upload_data.txt \
https://api.example.com/upload
示例5:查询参数测试
# 带查询参数的 GET
hey -z 30s -c 50 \
"https://api.example.com/search?q=golang&page=1&limit=20"
# 多个查询参数
hey -z 30s -c 50 \
"https://api.example.com/products?category=electronics&min_price=100&max_price=1000&sort=price_desc"
5. 高级用法
读取 URL 列表文件
# 创建 URL 文件
cat > urls.txt << EOF
https://api.example.com/users/1
https://api.example.com/users/2
https://api.example.com/users/3
https://api.example.com/products/1
https://api.example.com/products/2
EOF
# 从文件读取 URL
hey -z 1m -c 10 -m GET < urls.txt
输出结果到文件
# 保存输出到文件
hey -z 1m -c 50 https://example.com > result.txt
# 只保存摘要信息
hey -z 1m -c 50 https://example.com 2>&1 | tee result.txt
使用自定义 DNS
# 指定 DNS 服务器
hey -z 30s -c 20 \
-host "api.example.com:8.8.8.8" \
https://api.example.com/api
6. 实战场景案例
场景1:电商网站压力测试
# 首页访问
hey -z 5m -c 200 -q 50 \
-H "Accept: text/html,application/xhtml+xml" \
-H "Accept-Language: zh-CN,zh;q=0.9" \
https://shop.example.com
# 商品列表页
hey -z 3m -c 100 -q 30 \
"https://shop.example.com/products?category=electronics&page=1"
# 商品详情页
hey -z 2m -c 50 \
-H "Referer: https://shop.example.com/products" \
https://shop.example.com/product/123
# 下单接口
hey -z 1m -c 20 -m POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer user_token" \
-d '{"product_id":123,"quantity":1,"address_id":456}' \
https://api.shop.example.com/orders
场景2:API 网关测试
# 测试多个端点
#!/bin/bash
ENDPOINTS=(
"/api/v1/users"
"/api/v1/products"
"/api/v1/orders"
"/api/v1/payments"
)
BASE_URL="https://api.example.com"
for endpoint in "${ENDPOINTS[@]}"; do
echo "Testing: ${BASE_URL}${endpoint}"
hey -z 30s -c 50 "${BASE_URL}${endpoint}"
echo "====================================="
sleep 5
done
场景3:微服务链路测试
# 模拟完整用户流程
# 1. 用户登录
hey -n 1000 -c 20 -m POST \
-H "Content-Type: application/json" \
-d '{"username":"test","password":"password"}' \
https://auth.example.com/login
# 2. 获取用户信息
hey -n 2000 -c 50 -m GET \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." \
https://user.example.com/profile
# 3. 浏览商品
hey -n 5000 -c 100 -m GET \
https://product.example.com/items?page=1&size=20
# 4. 添加到购物车
hey -n 2000 -c 30 -m POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." \
-d '{"item_id":123,"quantity":2}' \
https://cart.example.com/add
7. 输出结果解读
运行测试后的输出示例:
Summary:
Total: 10.0024 secs
Slowest: 2.1234 secs
Fastest: 0.0123 secs
Average: 0.4567 secs
Requests/sec: 499.88
Total data: 1.23 MB
Size/request: 1234 bytes
Response time histogram:
0.012 [1] |
0.223 [250] |∎∎∎∎∎∎∎∎∎∎
0.433 [500] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎
0.644 [200] |∎∎∎∎∎∎∎∎
0.855 [30] |∎
1.066 [10] |
1.277 [5] |
1.488 [3] |
1.699 [1] |
1.910 [0] |
2.121 [1] |
Latency distribution:
10% in 0.1234 secs
25% in 0.2345 secs
50% in 0.3456 secs
75% in 0.5678 secs
90% in 0.7890 secs
95% in 1.1234 secs
99% in 1.9876 secs
Details (average, fastest, slowest):
DNS+dialup: 0.0012 secs, 0.0001 secs, 0.0123 secs
DNS-lookup: 0.0005 secs, 0.0000 secs, 0.0056 secs
req write: 0.0001 secs, 0.0000 secs, 0.0012 secs
resp wait: 0.3456 secs, 0.0101 secs, 1.9876 secs
resp read: 0.0002 secs, 0.0000 secs, 0.0023 secs
Status code distribution:
[200] 1000 responses
关键指标解读:
- Requests/sec:QPS,系统吞吐量
- Average:平均响应时间
- p50/p95/p99:分位响应时间
- Latency distribution:延迟分布
- Status code:HTTP 状态码分布
8. 最佳实践
渐进式压力测试
#!/bin/bash
# 渐进增加并发数
for concurrent in 10 50 100 200 500 1000; do
echo "测试并发数: ${concurrent}"
hey -z 30s -c ${concurrent} https://api.example.com
echo "等待10秒进行下一轮测试..."
sleep 10
done
带思考时间的测试
#!/bin/bash
# 模拟用户行为,间隔1秒
for i in {1..1000}; do
# 每次请求间隔1秒
hey -n 1 -c 1 https://api.example.com/api/endpoint
sleep 1
done
混合场景测试
#!/bin/bash
# 混合不同比例的请求
while true; do
# 80% GET请求
for i in {1..8}; do
hey -n 1 -c 1 https://api.example.com/get-endpoint &
done
# 15% POST请求
for i in {1..1}; do
hey -n 1 -c 1 -m POST \
-H "Content-Type: application/json" \
-d '{"action":"update"}' \
https://api.example.com/post-endpoint &
done
# 5% DELETE请求
hey -n 1 -c 1 -m DELETE \
https://api.example.com/delete-endpoint &
wait
sleep 0.1
done
9. 问题诊断
常见错误及解决
# 1. 连接被拒绝
# 检查服务是否启动
netstat -an | grep :8080
# 2. 太多打开文件
# Linux/Mac: 增加文件描述符限制
ulimit -n 100000
# 3. 端口耗尽
# 减少并发数
hey -c 1000 ... # 而不是 20000
# 4. DNS 解析问题
# 使用 -host 指定 IP
hey -host "api.example.com:1.2.3.4" https://api.example.com
调试输出
# 显示详细调试信息
hey -v -z 10s -c 10 https://example.com
# 跟踪重定向
hey -disable-redirects -z 10s -c 10 https://example.com
10. 与监控工具结合
实时监控脚本
#!/bin/bash
# 持续监控 API 性能
while true; do
timestamp=$(date +"%Y-%m-%d %H:%M:%S")
echo "======= ${timestamp} ======="
result=$(hey -z 5s -c 50 https://api.example.com/health 2>&1 | grep "Requests/sec")
qps=$(echo $result | awk '{print $2}')
echo "当前 QPS: ${qps}"
if (( $(echo "$qps < 100" | bc -l) )); then
echo "警告: QPS 低于 100"
fi
sleep 60
done
生成测试报告
#!/bin/bash
# 生成 HTML 报告
echo "<html><body><h1>压力测试报告</h1>" > report.html
for endpoint in "/api/users" "/api/products" "/api/orders"; do
echo "<h2>测试端点: ${endpoint}</h2>" >> report.html
echo "<pre>" >> report.html
hey -z 30s -c 100 "https://api.example.com${endpoint}" 2>&1 >> report.html
echo "</pre><hr>" >> report.html
done
echo "</body></html>" >> report.html
11. 与其他工具比较
| 工具 | 优点 | 缺点 |
|---|---|---|
| hey | 安装简单,结果清晰,支持持续测试 | 功能相对基础 |
| ab | Apache 自带,历史悠久 | 不支持持续测试,结果不如 hey 详细 |
| wrk | 性能极高,支持 Lua 脚本 | 安装稍复杂,不支持 Windows 原生 |
| vegeta | 功能强大,支持各种输出格式 | 配置稍复杂 |
| k6 | 现代化,支持 JavaScript 脚本 | 需要学习脚本语法 |
12. 实际工作流示例
完整的压力测试流程
#!/bin/bash
# 完整的 API 压力测试流程
echo "1. 预热阶段 (10% 负载)"
hey -z 30s -c 20 https://api.example.com
echo "等待 30 秒..."
sleep 30
echo "2. 中等负载阶段 (50% 负载)"
hey -z 2m -c 100 https://api.example.com
echo "等待 60 秒..."
sleep 60
echo "3. 峰值负载阶段 (100% 负载)"
hey -z 3m -c 200 https://api.example.com
echo "4. 稳定性测试 (80% 负载持续 5 分钟)"
hey -z 5m -c 160 https://api.example.com
echo "5. 恢复测试 (负载逐步降低)"
for concurrent in 160 120 80 40 20 10; do
echo "并发数: ${concurrent}"
hey -z 1m -c ${concurrent} https://api.example.com
done
echo "压力测试完成!"
通过这个完整指南,您可以全面掌握 hey 工具的使用,从基本测试到复杂的生产环境压力测试场景。