流量限制(Rate Limiting)的重要性#
在当今的 API 经济中,流量限制(Rate Limiting)在系统稳定性、安全性和成本效率方面起着至关重要的作用。下面详细说明其重要性。

服务器负载管理#
API 可能会收到不可预测数量的请求。例如,突然爆火的应用或意外的流量激增(即"流量高峰")可能导致服务器过载。通过设置流量限制,可以控制最大请求量,确保服务器维持良好性能。
公平性保障#
流量限制是保障所有用户公平访问 API 的重要手段。它防止某些用户或应用独占资源,保护其他用户的体验。
提升安全性#
流量限制对于防御恶意请求、DoS(拒绝服务)攻击和机器人滥用非常有效。通过检测并限制异常请求模式,可以保护 API 及整个系统。
成本管理#
许多云服务商和基础设施服务会按请求数或数据流量计费。若允许无限制请求,可能导致意外的高额费用。通过设置流量限制,可以更好地预测成本,避免不必要的支出。
Kong 的流量限制基本机制#
Kong Gateway 是一个开源 API 网关,便于管理和保护 API。企业和开发者常用它提升 API 的安全性、性能和可靠性。Kong Gateway 的流量限制功能用于控制 API 端点的流量,通过插件形式提供,配置简单灵活。
Kong 的流量限制插件工作原理如下:
- 请求计数
插件会统计请求数,在指定时间窗口(秒、分、时、天等)内超出设定阈值时进行限制。
- 超限时的处理
超出阈值的请求会被拒绝,返回 HTTP 状态码(通常为 429 Too Many Requests),也可自定义错误信息。
- 存储方式
计数信息可存储在本地内存或 Redis 等外部存储中,从而保证分布式环境下的一致性。
- 灵活的应用范围
- 按 Service:为特定 API 设置限制
- 按 Consumer:为不同用户或应用设置不同限制
- 按 Route:仅为特定 API 端点设置限制
基本配置:Kong 流量限制插件#
Kong 提供两种流量限制插件,均可按时间单位限制请求数。例如,可轻松设置每分钟最多 3 次请求。
- [OSS]
https://docs.konghq.com/hub/kong-inc/rate-limiting/
- [Enterprise]
https://docs.konghq.com/hub/kong-inc/rate-limiting-advanced/
插件配置#
本文以 OSS 版为例。首先创建测试用 Service 和 Route。
1
2
3
4
5
6
7
| curl -i -X POST http://localhost:8001/services/ \
--data name=uuid_service \
--data url=http://httpbin.org/uuid
curl -i -X POST http://localhost:8001/services/uuid_service/routes/ \
--data name=uuid_route \
--data paths=/uuid
|
未设置限制时,可以无限制生成 UUID。
1
2
3
4
| curl http://localhost:8000/uuid
{
"uuid": "84677e6f-911c-457b-a74f-d825e84248cb"
}
|
接下来,为 Service 创建 Rate Limiting 插件。
1
2
3
| curl -X POST http://localhost:8001/services/uuid_service/plugins \
--data "name=rate-limiting" \
--data "config.minute=5"
|
该命令会为 uuid_service
Service 注册如下配置:
- 插件:Rate Limiting
- 限制:每分钟最多访问 5 次
如需应用于 Route 或 Consumer,只需将 services/uuid_service
部分相应修改即可。
动作验证#
前 5 次访问均正常:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| curl http://localhost:8000/uuid
{
"uuid": "6d1c137e-3707-4d50-a64c-89d7ac083ed0"
}
curl http://localhost:8000/uuid
{
"uuid": "d3184480-124d-4ec4-a03a-c3f497260e2c"
}
curl http://localhost:8000/uuid
{
"uuid": "3fb50124-535c-4851-b63c-4646054b88b4"
}
curl http://localhost:8000/uuid
{
"uuid": "59db16f2-6aeb-4301-b88e-7fe28c3d0558"
}
curl http://localhost:8000/uuid
{
"uuid": "56f4472b-5e68-4c9a-afcb-28a2899cc95b"
}
|
第 6 次起会返回错误:
1
2
3
4
5
| curl http://localhost:8000/uuid
{
"message":"API rate limit exceeded",
"request_id":"090e45286c55141b7fc47640d3df482d"
}
|
进阶配置#
错误信息与响应码#
如需自定义错误信息和错误码,可如下设置:
1
2
3
4
5
| curl -X POST http://localhost:8001/services/uuid_service/plugins \
--data "name=rate-limiting" \
--data "config.minute=5" \
--data "config.error_code=429" \
--data "config.error_message=请稍等片刻"
|
超过 5 次访问时,会返回自定义响应:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| curl -S http://localhost:8000/uuid
{
"message":"请稍等片刻",
"request_id":"fd0f1d3851d1487748035047959b4242"
}%
curl -I http://localhost:8000/uuid
HTTP/1.1 429 Too Many Requests
Date: Tue, 03 Dec 2024 08:21:25 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
X-RateLimit-Limit-Minute: 5
X-RateLimit-Remaining-Minute: 0
RateLimit-Reset: 35
Retry-After: 35
RateLimit-Remaining: 0
RateLimit-Limit: 5
Content-Length: 84
X-Kong-Response-Latency: 1
Server: kong/3.8.0.0-enterprise-edition
X-Kong-Request-Id: 2987f03c7d71364a57f6904500d3a915
|
请求计数器与 Redis 的使用#
Kong 的 Rate Limiting 插件支持将请求计数器存储在数据库、内存或 Redis 中。不同存储方式各有特点,应根据实际环境选择。
存储在数据库#
如将计数器存储在数据库,所有 Kong 节点需连接同一数据库,实现节点间计数共享。但在 dbless 或 hybrid 模式下无法使用。
存储在内存#
适用于单节点高性能场景,分布式环境下有限制。
存储在 Redis#
使用 Redis 可实现集群范围内的计数共享。所有 Kong 节点指向同一 Redis 实例,保证全局准确计数。Redis 性能高,适合大流量场景。但需额外部署 Redis,并考虑 Redis 故障时的应对。
Redis 配置示例#
用如下文件通过 docker compose 部署 Redis,"--requirepass kong"
设置了 Redis 密码。
1
2
3
4
5
6
7
8
9
| version: "3.9"
services:
redis:
image: redis:latest
container_name: redis-no-auth
ports:
- "6379:6379"
command: ["redis-server", "--requirepass", "kong"]
|
用如下命令配置 Rate Limiting:
1
2
3
4
5
6
7
8
| curl -X POST http://localhost:8001/services/uuid_service/plugins \
--data "name=rate-limiting" \
--data "config.minute=5" \
--data "config.policy=redis" \
--data "config.redis.host=18.178.66.113" \
--data "config.redis.port=6379" \
--data "config.redis.username=default" \
--data "config.redis.password=kong"
|
config.policy=redis
:计数器存储在 Redisconfig.host
:Redis 主机名config.port
:Redis 端口config.username
:Redis 用户名(默认 default
)config.password
:Redis 密码(本例为 kong
)
多次请求后,可用如下命令在 Redis 内查看计数器:
1
2
3
4
5
6
7
8
9
10
11
12
13
| # 进入 Redis 容器
> docker exec -it 51 sh
# 用密码登录
> redis-cli -a kong
# 发送一次请求后列出所有 key
127.0.0.1:6379> keys *
1) "ratelimit:00000000-0000-0000-0000-000000000000:628a172c-a98f-4355-a09b-f78f8e7f2562:172.21.0.1:1733231580000:minute"
# 查看该 key 的值,应为 1
127.0.0.1:6379> get ratelimit:00000000-0000-0000-0000-000000000000:628a172c-a98f-4355-a09b-f78f8e7f2562:172.21.0.1:1733231580000:minute
"1"
|
按时间动态调整限制#
结合 Pre-function 和 Rate Limiting,可以根据时间动态调整流量限制。实际操作中,为同一 Service 创建两个 Route,分别设置不同 Header 条件。通过 Pre-function 根据时间设置不同 Header,实现该功能。

首先创建测试用 Service。
1
2
3
| curl -i -X POST http://localhost:8001/services \
--data "name=httpbin" \
--data "url=https://httpbin.konghq.com/anything"
|
然后创建两个 Route,路径相同但 Header 条件不同。
1
2
3
4
5
6
7
8
9
| curl -i -X POST http://localhost:8001/services/httpbin/routes \
--data "name=peak" \
--data "paths=/httpbin" \
--data "headers.X-Peak=true"
curl -i -X POST http://localhost:8001/services/httpbin/routes \
--data "name=off-peak" \
--data "paths=/httpbin" \
--data "headers.X-Off-Peak=true"
|
接着为每个 Route 配置 Rate Limiting 插件。
1
2
3
4
5
6
7
| curl -i -X POST http://localhost:8001/routes/peak/plugins/ \
--data "name=rate-limiting" \
--data "config.minute=10"
curl -i -X POST http://localhost:8001/routes/off-peak/plugins/ \
--data "name=rate-limiting" \
--data "config.minute=60"
|
最后用 Pre-function 根据时间设置 Header,使流量路由到正确的 Route。
将以下内容保存为 ratelimit.lua
。该函数根据操作系统时间判断当前时段,并据此设置 Header(08:00-17:00 为 X-Peak,否则为 X-Off-Peak)。
1
2
3
4
5
6
7
| local hour = os.date("*t").hour
if hour >= 8 and hour <= 17
then
kong.service.request.set_header("X-Peak","true")
else
kong.service.request.set_header("X-Off-Peak","true")
end
|
设置为 rewrite 阶段执行:
1
2
3
| curl -i -X POST http://localhost:8001/plugins \
--form "name=pre-function" \
--form "config.rewrite[1][email protected]"
|
这样即可实现工作时间(08:00-17:00)每分钟 10 次,非工作时间每分钟 60 次的流量限制。
OSS 与 Enterprise 的区别#
Rate Limiting Advanced 文档 介绍了与 OSS 插件的区别:
- 多重限制与多窗口支持
- 例如设置每天 1000 次限制,但若全部集中在最后一分钟发送,API 仍会被压垮。可同时设置每天 1000 次 + 每分钟 60 次等多重限制,解决该问题。
- 支持 Redis Sentinel、Redis 集群和 Redis SSL
- 更高吞吐量和准确性
- 更多流量限制算法
- 支持 Consumer groups
本文介绍了 Kong Gateway 流量限制的重要性、基本机制及配置方法。流量限制是保障 API 稳定运行、安全和成本管理的关键技术。得益于 Kong 灵活的插件设计,这一功能可以高效便捷地实现。
Kong OSS 版已能满足大多数需求,如有更复杂场景可考虑 Enterprise 版,企业版提供更多高级功能和更高性能。
希望本文能为你用 Kong 管理 API 提供参考。欢迎关注后续更多 API 与微服务运维技术博客!