<span class="nav-link-with-icon">Distributed RateLimit <img src="https://doc.traefik.io/traefik-hub/img/ps-traefik-hub-logo-light.svg" class="menu-icon" alt="Traefik Hub API Gateway"></span>
Traefik Hub 功能
此中间件仅在 Traefik Hub 中提供。了解更多 Traefik Hub 高级功能。
Distributed RateLimit 中间件确保在整个集群范围内按时间限制请求数量,而不仅限于单个代理。
它基于令牌桶实现。
配置示例¶
以下高级配置启用了以 Redis 为后端的 Distributed RateLimit 中间件,从而实现集群范围的限流。
# Here, a limit of 100 requests per second is allowed.
# In addition, a burst of 200 requests is allowed.
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: test-distributedratelimit
namespace: traefik
spec:
plugin:
distributedRateLimit:
burst: 200
limit: 100
period: 1s
denyOnError: false
responseHeaders: true
sourceCriterion:
ipStrategy:
excludedIPs:
- 172.20.176.201
store:
redis:
endpoints:
- my-release-redis-master.default.svc.cluster.local:6379
# Use the field password of the Secret redis in the same namespace
password: urn:k8s:secret:redis:password
timeout: 500msapiVersion: v1
kind: Secret
metadata:
name: redis
namespace: traefik
stringData:
password: mysecret12345678速率与突发容量¶
速率由 limit 除以 period 定义。
要实现低于每秒 1 个请求的速率,请将 period 设为大于 1 秒的值。
此中间件基于令牌桶实现。
在这个类比中,limit 和 period 参数定义令牌桶补充令牌的速率,burst 则是令牌桶的大小(容量)。
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: test-ratelimit
spec:
plugin:
distributedRateLimit:
burst: 100
period: 1m
limit: 6
在上述示例中,中间件最多允许 100 个并行连接(burst)。
每个连接消耗一个令牌。100 个令牌全部消耗后,其他连接会被阻止,直到桶中至少有一个可用令牌。
当桶未满时,每 10 秒生成一个令牌,即每 1 分钟生成 6 个(period / limit)。
配置选项¶
| 字段 | 说明 | 默认值 | 必填 |
|---|---|---|---|
limit |
配合 period 定义速率的请求数。0 表示不限流。 更多信息见此处。 |
0 | 否 |
period |
用于定义速率的时间周期。 更多信息见此处。 |
1s | 否 |
burst |
同一时刻允许通过的最大请求数。 更多信息见此处。 |
1 | 否 |
denyOnError |
限流存储(Redis)不可用时是否拒绝请求。设为 false 时,若无法连接 Redis,则允许请求通过。 |
true | 否 |
responseHeaders |
是否向响应中注入限流头(X-RateLimit-Limit、X-RateLimit-Remaining、X-RateLimit-Reset)。 |
false | 否 |
store.redis.endpoints |
要连接的 Redis 实例端点(例如 redis.traefik-hub.svc.cluster.local:6379)。 |
"" | 是 |
store.redis.username |
Traefik Hub 连接 Redis 时使用的用户名。 | "" | 否 |
store.redis.password |
Traefik Hub 连接 Redis 时使用的 password。 | "" | 否 |
store.redis.database |
Traefik Hub 用于存储信息的数据库。Redis Cluster 模式下不可用(仅支持数据库 0)。 |
0 | 否 |
store.redis.timeout |
Redis 连接的拨号、读取和写入操作所使用的超时时间。 | "" | 否 |
store.redis.cluster |
启用 Redis Cluster 模式。设置为 {} 时启用;省略时禁用。不能与 store.redis.sentinel 同时使用。 |
- | 否 |
store.redis.sentinel.masterSet |
Redis Sentinel 主节点集合名称。不能与 store.redis.cluster 同时使用。 |
"" | 是(使用 Sentinel 时) |
store.redis.sentinel.username |
向 Redis Sentinel 认证时使用的用户名。 | "" | 否 |
store.redis.sentinel.password |
向 Redis Sentinel 认证时使用的密码。 | "" | 否 |
store.redis.tls.ca |
自定义 CA 证书包。 | "" | 否 |
store.redis.tls.cert |
TLS 证书。 | "" | 否 |
store.redis.tls.key |
TLS 密钥。 | "" | 否 |
store.redis.tls.insecureSkipVerify |
允许跳过 TLS 验证。 | false | 否 |
sourceCriterion.requestHost |
是否将请求主机作为来源。sourceCriterion 的更多信息见此处。 |
false | 否 |
sourceCriterion.requestHeaderName |
用于对传入请求进行分组的请求头名称。sourceCriterion 的更多信息见此处。 |
"" | 否 |
sourceCriterion.ipStrategy.depth |
从右侧开始,在 X-Forwarded-For 头中选择 IP 的深度位置。0 表示不使用深度。 如果大于 X-Forwarded-For 中的 IP 总数,客户端 IP 为空。如果大于 0,则不计算 excludedIPs 选项。更多信息参阅下文的 sourceCriterion、ipStrategy 和 depth。 |
0 | 否 |
sourceCriterion.ipStrategy.excludedIPs |
允许 Traefik 扫描 X-Forwarded-For 头,选取第一个不在此列表中的 IP。如果指定了 depth,则忽略 excludedIPs。更多信息参阅下文的 sourceCriterion、ipStrategy 和 excludedIPs。 |
否 |
sourceCriterion 来源判定标准¶
sourceCriterion 选项定义将请求归为同一来源时使用的判定标准。
如果同时定义多种策略,将报错。
如果均未设置,默认使用请求的远程地址字段(作为 ipStrategy)。
ipStrategy IP 策略¶
ipStrategy 选项定义 depth 和 excludedIPs 两个参数,用于配置 Traefik 如何确定客户端 IP。
限流作为中间件,在实际向后端代理请求之前执行。
此外,前一网络跳点仅在代理过程的最后阶段才会追加到 X-Forwarded-For 中,此时请求已经过限流。
因此,在限流期间,前一网络跳点尚未出现在 X-Forwarded-For 中,无法找到它,也不能依赖它。
sourceCriterion.ipStrategy.depth 深度¶
如果 depth 设置为 2,且请求的 X-Forwarded-For 头为 "10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1",则“真实”客户端 IP 为 "10.0.0.1"(深度为 4),但用作判定标准的 IP 是 "12.0.0.1"(depth=2)。
X-Forwarded-For |
depth |
clientIP(客户端 IP) |
|---|---|---|
"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1" |
1 |
"13.0.0.1" |
"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1" |
3 |
"11.0.0.1" |
"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1" |
5 |
"" |
sourceCriterion.ipStrategy.excludedIPs 排除的 IP¶
尽管名称可能引起误解,此选项并不是将某个 IP 排除在限流器之外,因此不能用来停用某些 IP 的限流。
excludedIPs 用于解决两类略有不同的使用场景:
- 区分位于同一组反向代理后面的 IP,使它们各自独立计入自己的限流“桶”(参见令牌桶)。
在这种情况下,应将
excludedIPs设置为要排除的X-Forwarded-For IPs列表,从而找到真正的客户端 IP。
将每个 IP 用作独立来源的示例:
X-Forwarded-For |
excludedIPs | clientIP(客户端 IP) |
|---|---|---|
"10.0.0.1,11.0.0.1,12.0.0.1" |
"11.0.0.1,12.0.0.1" |
"10.0.0.1" |
"10.0.0.2,11.0.0.1,12.0.0.1" |
"11.0.0.1,12.0.0.1" |
"10.0.0.2" |
- 将一组 IP(同样位于共同的一组反向代理之后)归为一组,使其被视为同一来源,并全部计入同一个限流桶。
将多个 IP 归为同一来源的示例:
X-Forwarded-For |
excludedIPs | clientIP(客户端 IP) |
|---|---|---|
"10.0.0.1,11.0.0.1,12.0.0.1" |
"12.0.0.1" |
"11.0.0.1" |
"10.0.0.2,11.0.0.1,12.0.0.1" |
"12.0.0.1" |
"11.0.0.1" |
"10.0.0.3,11.0.0.1,12.0.0.1" |
"12.0.0.1" |
"11.0.0.1" |
store 存储¶
Distributed Rate Limit 中间件使用持久化 KV 存储保存数据。
参阅 Redis 选项来配置 Redis 连接。
Redis 服务器的连接参数配置在 Middleware 部署中。
支持以下 Redis 模式:
- 单实例模式
- Redis Cluster 集群模式
- Redis Sentinel 哨兵模式
更多 Redis 信息,建议参阅 Redis 官方文档。
提示
如果使用 Redis 单实例模式或 Redis Sentinel,可以配置 database 字段。
如果使用 Redis Cluster,此值不会生效(仅可使用数据库 0)。
此时将显示一条警告,并忽略该值。