Hey 压力测试工具完整使用指南

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安装简单,结果清晰,支持持续测试功能相对基础
abApache 自带,历史悠久不支持持续测试,结果不如 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 工具的使用,从基本测试到复杂的生产环境压力测试场景。

Comments

No comments yet. Why don’t you start the discussion?

发表回复