跳到主要内容
版本:3.10.x

配置限流

限流允许你限制客户端在特定时间窗口内可以向 API 发起的请求数量。它可以防止后端服务因请求过多而被压垮,并确保所有用户公平使用服务。

API7 企业版提供两个用于限流的插件:

  • limit-count:简单限流插件,用于统计固定时间窗口内的请求数。
  • limit-count-advanced:高级版本,支持滑动窗口、多规则和 Redis Sentinel。

以下场景复用同一个服务和路由。应用下一个场景前,请先验证当前场景,因为后续场景会更新路由的插件配置,并成为唯一生效的限流器。

前置条件​

  • API7 企业版实例正在运行。
  • 已创建网关组,并且网关实例正在运行。
  • 从控制台获取 Token。

配置基础限流​

limit-count 插件适合简单限流场景,例如限制每个 IP 地址每分钟最多 5 个请求。

curl -k "https://localhost:7443/apisix/admin/services/rate-limit-service?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "rate-limit-service",
"upstream": {
"type": "roundrobin",
"scheme": "http",
"nodes": [
{
"host": "httpbin.org",
"port": 80,
"weight": 100
}
]
}
}'

curl -k "https://localhost:7443/apisix/admin/routes/rate-limit-route?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "rate-limit-route",
"methods": ["GET"],
"paths": ["/get"],
"service_id": "rate-limit-service",
"plugins": {
"limit-count": {
"count": 5,
"time_window": 60,
"rejected_code": 429,
"rejected_msg": "Too Many Requests",
"key": "remote_addr",
"policy": "local"
}
}
}'

发送六次 GET 请求。前五次应成功,第六次应返回 429:

for i in {1..6}; do
curl -s -o /dev/null -w '%{http_code}\n' "http://127.0.0.1:9080/get"
done

配置分布式限流​

在多节点网关部署中,使用 redis 策略可以在所有节点之间共享限流计数器。

curl -k "https://localhost:7443/apisix/admin/services/rate-limit-service?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "rate-limit-service",
"upstream": {
"type": "roundrobin",
"scheme": "http",
"nodes": [
{
"host": "httpbin.org",
"port": 80,
"weight": 100
}
]
}
}'

curl -k "https://localhost:7443/apisix/admin/routes/rate-limit-route?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "rate-limit-route",
"methods": ["GET"],
"paths": ["/get"],
"service_id": "rate-limit-service",
"plugins": {
"limit-count": {
"count": 5,
"time_window": 60,
"rejected_code": 429,
"policy": "redis",
"redis_host": "127.0.0.1",
"redis_port": 6379,
"redis_password": "your-password",
"redis_database": 0,
"allow_degradation": true
}
}
}'

将 allow_degradation 设置为 true 后,即使 Redis 服务器不可达,也会允许流量通过。

确认 Redis 可达后,发送六次 GET 请求。前五次应成功,第六次应返回 429:

for i in {1..6}; do
curl -s -o /dev/null -w '%{http_code}\n' "http://127.0.0.1:9080/get"
done

配置高级限流​

limit-count-advanced 插件支持滑动窗口算法,可以避免固定窗口边界处可能出现的流量突增。它还允许在单个插件实例中定义多条规则。

curl -k "https://localhost:7443/apisix/admin/services/rate-limit-service?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "rate-limit-service",
"upstream": {
"type": "roundrobin",
"scheme": "http",
"nodes": [
{
"host": "httpbin.org",
"port": 80,
"weight": 100
}
]
}
}'

curl -k "https://localhost:7443/apisix/admin/routes/rate-limit-route?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "rate-limit-route",
"methods": ["GET"],
"paths": ["/get"],
"service_id": "rate-limit-service",
"plugins": {
"limit-count-advanced": {
"window_type": "sliding",
"policy": "local",
"rejected_code": 429,
"rules": [
{
"count": 3,
"time_window": 60,
"key": "$remote_addr"
},
{
"count": 1000,
"time_window": 3600,
"key": "$http_x_api_key"
}
]
}
}
}'

在此示例中,每个客户端 IP 每分钟最多 3 个请求,每个 API Key 每小时最多 1,000 个请求。

发送四次 GET 请求。前三次应成功,第四次应返回 429:

for i in {1..4}; do
curl -s -o /dev/null -w '%{http_code}\n' "http://127.0.0.1:9080/get" \
-H "X-API-Key: demo-client"
done

解读限流响应​

被拒绝的请求会收到配置的 429 Too Many Requests 响应。

如果应用配置后路由立即返回 404,请等待几秒钟,让最新配置下发到网关后再重试。

对于基础和分布式限流场景,如果启用了 show_limit_quota_header(默认为 true),响应还会包含 X-RateLimit 相关响应头:

HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 5
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 45

同时命中两条规则的高级限流请求可能包含每条规则各一组的配额响应头。如果未配置 header_prefix,响应头使用规则索引,例如第一条规则使用 X-1-RateLimit-Limit,第二条规则使用 X-2-RateLimit-Limit。如果第一条规则拒绝请求,后续规则不再评估,因此拒绝响应可能只包含第一条规则的响应头。

故障排查​

  • Redis 连接问题:确保网关节点能够通过网络访问 Redis 服务器,并且凭证正确。检查网关日志中是否存在连接错误。
  • limit-count 的 key_type 错误:如果 key 是 remote_addr 等请求变量名,将 key_type 设为 var;如果 key 是字面常量,将其设为 constant。
  • limit-count-advanced 的规则 key 无效:规则没有 key_type。它的 key 是变量表达式,因此变量需要 $ 前缀,例如 $remote_addr。没有变量引用的值会被跳过;如果所有规则都被跳过,网关默认返回 HTTP 500。
  • Redis 延迟:如果 Redis 延迟影响请求性能,可考虑对高频低延迟限制使用 local 策略,或调优基于 Redis 策略的 sync_interval。

后续步骤​