跳到正文
Træfɪk

RateLimit

rateLimit 中间件确保服务获得合理数量的请求,并允许你定义什么是合理。

它基于令牌桶实现。 在这个类比中,average 和 period 参数定义令牌桶补充令牌的速率,burst 则是令牌桶的大小(容量)。

速率与突发容量

速率由 average 除以 period 定义。 要实现低于每秒 1 个请求的速率,请将 period 设为大于 1 秒的值。

配置示例

# Here, an average of 100 requests per second is allowed.
# In addition, a burst of 200 requests is allowed.
# Redis distributed rate limiting is configured with all available options.
http:
  middlewares:
    test-ratelimit:
      rateLimit:
        average: 100
        period: 1s
        burst: 200
        redis:
          endpoints:
            - "redis-primary.example.com:6379"
            - "redis-replica.example.com:6379"
          username: "ratelimit-user"
          password: "secure-password"
          db: 2
          poolSize: 50
          minIdleConns: 10
          maxActiveConns: 200
          readTimeout: 3s
          writeTimeout: 3s
          dialTimeout: 5s
          tls:
            ca: "/etc/ssl/redis-ca.crt"
            cert: "/etc/ssl/redis-client.crt"
            key: "/etc/ssl/redis-client.key"
            insecureSkipVerify: false
# Here, an average of 100 requests per second is allowed.
# In addition, a burst of 200 requests is allowed.
# Redis distributed rate limiting is configured with all available options.
[http.middlewares]
  [http.middlewares.test-ratelimit.rateLimit]
    average = 100
    period = "1s"
    burst = 200
    [http.middlewares.test-ratelimit.rateLimit.redis]
      endpoints = ["redis-primary.example.com:6379", "redis-replica.example.com:6379"]
      username = "ratelimit-user"
      password = "secure-password"
      db = 2
      poolSize = 50
      minIdleConns = 10
      maxActiveConns = 200
      readTimeout = "3s"
      writeTimeout = "3s"
      dialTimeout = "5s"
      [http.middlewares.test-ratelimit.rateLimit.redis.tls]
        ca = "/etc/ssl/redis-ca.crt"
        cert = "/etc/ssl/redis-client.crt"
        key = "/etc/ssl/redis-client.key"
        insecureSkipVerify = false
# Here, an average of 100 requests per second is allowed.
# In addition, a burst of 200 requests is allowed.
# Redis distributed rate limiting is configured with all available options.
labels:
  - "traefik.http.middlewares.test-ratelimit.ratelimit.average=100"
  - "traefik.http.middlewares.test-ratelimit.ratelimit.period=1s"
  - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=200"
  - "traefik.http.middlewares.test-ratelimit.ratelimit.redis.endpoints=redis-primary.example.com:6379,redis-replica.example.com:6379"
  - "traefik.http.middlewares.test-ratelimit.ratelimit.redis.username=ratelimit-user"
  - "traefik.http.middlewares.test-ratelimit.ratelimit.redis.password=secure-password"
  - "traefik.http.middlewares.test-ratelimit.ratelimit.redis.db=2"
  - "traefik.http.middlewares.test-ratelimit.ratelimit.redis.poolSize=50"
  - "traefik.http.middlewares.test-ratelimit.ratelimit.redis.minIdleConns=10"
  - "traefik.http.middlewares.test-ratelimit.ratelimit.redis.maxActiveConns=200"
  - "traefik.http.middlewares.test-ratelimit.ratelimit.redis.readTimeout=3s"
  - "traefik.http.middlewares.test-ratelimit.ratelimit.redis.writeTimeout=3s"
  - "traefik.http.middlewares.test-ratelimit.ratelimit.redis.dialTimeout=5s"
  - "traefik.http.middlewares.test-ratelimit.ratelimit.redis.tls.ca=/etc/ssl/redis-ca.crt"
  - "traefik.http.middlewares.test-ratelimit.ratelimit.redis.tls.cert=/etc/ssl/redis-client.crt"
  - "traefik.http.middlewares.test-ratelimit.ratelimit.redis.tls.key=/etc/ssl/redis-client.key"
  - "traefik.http.middlewares.test-ratelimit.ratelimit.redis.tls.insecureSkipVerify=false"
// Here, an average of 100 requests per second is allowed.
// In addition, a burst of 200 requests is allowed.
// Redis distributed rate limiting is configured with all available options.
{
  "Tags": [
    "traefik.http.middlewares.test-ratelimit.ratelimit.average=100",
    "traefik.http.middlewares.test-ratelimit.ratelimit.period=1s",
    "traefik.http.middlewares.test-ratelimit.ratelimit.burst=200",
    "traefik.http.middlewares.test-ratelimit.ratelimit.redis.endpoints=redis-primary.example.com:6379,redis-replica.example.com:6379",
    "traefik.http.middlewares.test-ratelimit.ratelimit.redis.username=ratelimit-user",
    "traefik.http.middlewares.test-ratelimit.ratelimit.redis.password=secure-password",
    "traefik.http.middlewares.test-ratelimit.ratelimit.redis.db=2",
    "traefik.http.middlewares.test-ratelimit.ratelimit.redis.poolSize=50",
    "traefik.http.middlewares.test-ratelimit.ratelimit.redis.minIdleConns=10",
    "traefik.http.middlewares.test-ratelimit.ratelimit.redis.maxActiveConns=200",
    "traefik.http.middlewares.test-ratelimit.ratelimit.redis.readTimeout=3s",
    "traefik.http.middlewares.test-ratelimit.ratelimit.redis.writeTimeout=3s",
    "traefik.http.middlewares.test-ratelimit.ratelimit.redis.dialTimeout=5s",
    "traefik.http.middlewares.test-ratelimit.ratelimit.redis.tls.ca=/etc/ssl/redis-ca.crt",
    "traefik.http.middlewares.test-ratelimit.ratelimit.redis.tls.cert=/etc/ssl/redis-client.crt",
    "traefik.http.middlewares.test-ratelimit.ratelimit.redis.tls.key=/etc/ssl/redis-client.key",
    "traefik.http.middlewares.test-ratelimit.ratelimit.redis.tls.insecureSkipVerify=false"
  ]
}
# Here, an average of 100 requests per second is allowed.
# In addition, a burst of 200 requests is allowed.
# Redis distributed rate limiting is configured with all available options.
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: test-ratelimit
spec:
  rateLimit:
    average: 100
    period: 1s
    burst: 200
    redis:
      endpoints:
        - "redis-primary.example.com:6379"
        - "redis-replica.example.com:6379"
      secret: redis-credentials
      db: 2
      poolSize: 50
      minIdleConns: 10
      maxActiveConns: 200
      readTimeout: 3s
      writeTimeout: 3s
      dialTimeout: 5s
      tls:
        caSecret: redis-ca
        certSecret: redis-client-cert
        insecureSkipVerify: false

---
apiVersion: v1
kind: Secret
metadata:
  name: redis-credentials
  namespace: default
data:
  username: cmF0ZWxpbWl0LXVzZXI=  # base64 encoded "ratelimit-user"
  password: c2VjdXJlLXBhc3N3b3Jk  # base64 encoded "secure-password"

---
apiVersion: v1
kind: Secret
metadata:
  name: redis-ca
  namespace: default
data:
  tls.ca: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t...

---
apiVersion: v1
kind: Secret
metadata:
  name: redis-client-cert
  namespace: default
data:
  tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t...
  tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0t...

配置选项

字段 说明 默认值 必填
average 配合 period 定义速率的请求数。
0 表示不限流。
更多信息见此处。
0 否
period 用于定义速率的时间周期。
更多信息见此处。
1s 否
burst 同一时刻允许通过的最大请求数。
更多信息见此处。
1 否
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 允许扫描 X-Forwarded-For 头,选取第一个不在此列表中的 IP。
如果指定了 depth,则忽略 excludedIPs。
更多信息参阅下文的 sourceCriterion、ipStrategy 和 excludedIPs。
否
sourceCriterion.ipStrategy.ipv6Subnet 如果提供 ipv6Subnet,且选中的 IP 为 IPv6,则将该 IP 转换为其所属子网的第一个 IP。
更多信息参阅下文的 sourceCriterion 和 ipStrategy.ipv6Subnet。
否
redis redis 配置通过 Redis 在多个 Traefik 实例之间存储限流令牌,启用分布式限流。这可以在 Traefik 代理集群中实施一致的限流。
未配置 Redis 时,Traefik 使用内存存储进行限流,仅对单个 Traefik 实例生效。
否
redis.endpoints 用于分布式限流的 Redis 服务器端点列表。可以指定多个端点,以适应 Redis 集群或高可用配置。 "localhost:6379" 否
redis.username Redis 认证使用的用户名。 "" 否
redis.password Redis 认证使用的密码。在 Kubernetes 中,可以通过 Secret 提供。 "" 否
redis.db 要选择的 Redis 数据库编号。 0 否
redis.poolSize 定义连接池中套接字连接的基础数量。设为 0 时,默认为 runtime.GOMAXPROCS 报告的每个 CPU 核心 10 个连接。
如果池中连接不足,会分配超出 poolSize 的新连接,最多达到 maxActiveConns。
0 否
redis.minIdleConns 连接池中要保持的最小空闲连接数。新建连接较慢时,此选项很有用。值为 0 表示不会自动关闭空闲连接。 0 否
redis.maxActiveConns 连接池在任意时刻可以分配的最大连接数。值为 0 表示不限制。 0 否
redis.readTimeout 套接字读取超时。达到此时间时,命令以超时失败,而非继续阻塞。零表示无超时。 3s 否
redis.writeTimeout 套接字写入超时。达到此时间时,命令以超时失败,而非继续阻塞。零表示无超时。 3s 否
redis.dialTimeout 建立新连接的超时。零表示无超时。 5s 否
redis.tls.ca 用于与 Redis 建立安全连接的证书颁发机构证书路径,默认使用系统证书包。 "" 否
redis.tls.cert 用于与 Redis 建立安全连接的公钥证书路径。设置此选项时,必须设置 key 选项。 "" 否
redis.tls.key 用于与 Redis 建立安全连接的私钥路径。设置此选项时,必须设置 cert 选项。 "" 否
redis.tls.insecureSkipVerify 如果 insecureSkipVerify 为 true,到 Redis 的 TLS 连接将接受服务端提供的任何证书,而不考虑其涵盖的主机名。 false 否

sourceCriterion 来源判定标准

sourceCriterion 选项定义将请求归为同一来源时使用的判定标准。 如果同时定义多种策略,将报错。 如果均未设置,默认使用请求的远程地址字段(作为 ipStrategy)。

ipStrategy IP 策略

ipStrategy 选项定义 depth、excludedIPs 和 ipv6Subnet 三个参数,用于配置 Traefik 如何确定客户端 IP。

限流作为中间件,在实际向后端代理请求之前执行。 此外,前一网络跳点仅在代理过程的最后阶段才会追加到 X-Forwarded-For 中,此时请求已经过限流。 因此,在限流期间,前一网络跳点尚未出现在 X-Forwarded-For 中,无法找到它,也不能依赖它。

sourceCriterion.ipStrategy.ipv6Subnet IPv6 子网

此策略仅适用于 Depth 和 RemoteAddr 策略。 如果提供 ipv6Subnet,且选中的 IP 为 IPv6,则将该 IP 转换为其所属子网的第一个 IP。

这可用于将 IPv6 地址按子网分组,防止通过获取新的 IPv6 地址来绕过此中间件。

  • 如果 ipv6Subnet 的值不在 0–128 范围内,则忽略此项。

ipv6Subnet 示例

提供 ipv6Subnet 时,IP 按以下方式转换。

IP ipv6Subnet clientIP(客户端 IP)
"::abcd:1111:2222:3333" 64 "::0:0:0:0"
"::abcd:1111:2222:3333" 80 "::abcd:0:0:0:0"
"::abcd:1111:2222:3333" 96 "::abcd:1111:0:0:0"

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 用于解决两类略有不同的使用场景:

  1. 区分位于同一组反向代理后面的 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"
  1. 将一组 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"

版权所有 © 头文件软件工作室

文档由 HeadFile Studio 翻译。

Traefik v3.7 中文快照 · 原文版权归 Traefik Labs 及贡献者所有 · MIT 许可证