速率限制

速率限制是一种限制入站请求的策略,指定主机或客户端在特定时间段内发送请求的次数。一旦达到限制(例如每秒 100 个请求),我们就说发出调用的客户端被限速。任何被限速的请求都会被拒绝,永远不会到达上游服务。

速率限制类型

Envoy 支持全局(分布式)和本地(非分布式)两个级别的速率限制。

全局 vs 本地速率限制

  • 全局速率限制:控制多个 Envoy 实例之间共享的上游集合的访问
  • 本地速率限制:适用于每个 Envoy 实例

全局和本地速率限制可以一起使用,Envoy 分两个阶段应用它们:首先应用本地速率限制,然后应用全局速率限制。

全局速率限制

全局或分布式速率限制在多个主机向少量上游服务器发送请求且平均延迟较低时很有用。

架构

Envoy 与实现定义 RPC/IDL 协议的任何外部速率限制服务集成。参考实现使用 Go、gRPC 和 Redis 作为后端。

配置概念

Actions、Descriptors 和 Descriptors List

在 Envoy 配置中,我们定义一组 actions。每个 action 包含速率限制操作列表。

rate_limits:
- actions:
  - header_value_match:
      descriptor_value: get_request
      headers:
      - name: :method
        prefix_match: GET
  - header_value_match:
      descriptor_value: path
      headers:
        - name: :path
          prefix_match: /api
- actions:
  - header_value_match:
      descriptor_value: post_request
      headers:
      - name: :method
        prefix_match: POST

客户端配置示例

routes:
- match:
    prefix: "/users"
  route:
    cluster: some_cluster
    rate_limits:
    - actions:
      - generic_key:
          descriptor_value: users
      - header_value_match:
          descriptor_value: post_request
          headers:
          - name: ":method"
            exact_match: POST
    - actions:
      - generic_key:
          descriptor_value: users
- match:
    prefix: "/api"
  route:
    cluster: some_cluster
    rate_limits:
    - actions:
      - generic_key:
          descriptor_value: api
      - request_headers:
          header_name: dev
          descriptor_key: dev_request

HTTP 过滤器配置

http_filters:
- name: envoy.filters.http.ratelimit
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit
    domain: some_domain
    enable_x_ratelimit_headers: DRAFT_VERSION_03
    rate_limit_service:
      transport_api_version: V3
      grpc_service:
          envoy_grpc:
            cluster_name: rate-limit-cluster

服务端配置

domain: some_domain
descriptors:
- key: generic_key
  value: users
  rate_limit:
    unit: MINUTE
    requests_per_unit: 20
  descriptors:
  - key: header_match
    value: post_request
    rate_limit:
      unit: MINUTE
      requests_per_unit: 10
- key: generic_key
  value: api
  descriptors:
  - key: dev_request
    value: true
    rate_limit:
      unit: SECOND
      requests_per_unit: 10
  - key: dev_request
    value: false
    rate_limit:
      unit: SECOND
      requests_per_unit: 5

本地速率限制

本地速率限制过滤器对过滤器链处理的入站连接应用令牌桶速率限制。

令牌桶算法

令牌桶算法基于桶中令牌的类比。桶以固定速率重新填充令牌。每次收到请求或连接时,我们检查桶中是否还有令牌。如果有,从桶中移除一个令牌,请求得到处理。如果没有令牌,请求被丢弃(即被限速)。

配置示例

基本配置

token_bucket:
  max_tokens: 5000
  tokens_per_fill: 100
  fill_interval: 30s
filter_enabled:
  default_value:
    numerator: 100
    denominator: HUNDRED
filter_enforced:
  default_value:
    numerator: 100
    denominator: HUNDRED

添加响应头部

token_bucket:
  max_tokens: 5000
  tokens_per_fill: 100
  fill_interval: 30s
filter_enabled:
  default_value:
    numerator: 100
    denominator: HUNDRED
filter_enforced:
  default_value:
    numerator: 100
    denominator: HUNDRED
response_headers_to_add:
  - append: false
    header:
      key: x-local-rate-limit
      value: 'true'

全局配置

http_filters:
- name: envoy.filters.http.local_ratelimit
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
    stat_prefix: http_local_rate_limiter
    token_bucket:
      max_tokens: 10000
      tokens_per_fill: 1000
      fill_interval: 1s

路由级别配置

route_config:
  virtual_hosts:
  - name: my_service
    domains: ["*"]
    routes:
    - match:
        prefix: /
      route:
        cluster: some_cluster
      typed_per_filter_config:
        envoy.filters.http.local_ratelimit:
          "@type": type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
          token_bucket:
              max_tokens: 10000
              tokens_per_fill: 1000
              fill_interval: 1s
            filter_enabled:
              default_value:
                numerator: 100
                denominator: HUNDRED
            filter_enforced:
              default_value:
                numerator: 100
                denominator: HUNDRED

使用 Descriptors 的本地速率限制

route_config:
  virtual_hosts:
  - name: my_service
    domains: ["*"]
    routes:
    - match:
        prefix: /
      route:
        cluster: some_cluster
        rate_limits:
        - actions:
          - header_value_match:
              descriptor_value: post_request
              headers:
              - name: ":method"
                exact_match: POST
          - header_value_match:
              descriptor_value: get_request
              headers:
              - name: ":method"
                exact_match: GET
typed_per_filter_config:
  envoy.filters.http.local_ratelimit:
    "@type": type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
    stat_prefix: some_stat_prefix
    token_bucket:
      max_tokens: 1000
      tokens_per_fill: 1000
      fill_interval: 60s
    filter_enabled:
      default_value:
        numerator: 100
        denominator: HUNDRED
    filter_enforced:
      default_value:
        numerator: 100
        denominator: HUNDRED
    descriptors:
    - entries:
      - key: header_match
        value: post_request
      token_bucket:
        max_tokens: 20
        tokens_per_fill: 5
        fill_interval: 30s
    - entries:
      - key: header_match
        value: get_request
      token_bucket:
        max_tokens: 50
        tokens_per_fill: 5
        fill_interval: 20s

速率限制统计

无论使用全局还是本地速率限制,Envoy 都会发出下表描述的指标。我们可以使用 stat_prefix 字段设置统计前缀。

速率限制器指标名称描述
Localenabled调用速率限制器的请求总数
Local/Globalok令牌桶的限速内响应总数
Localrate_limited没有可用令牌的响应总数(但不一定强制执行)
Localenforced被限速的请求总数(例如返回 HTTP 429)
Globalover_limit速率限制服务的超限响应总数
Globalerror联系速率限制服务的错误总数
Globalfailure_mode_allowed由于 failure_mode_deny 设置而允许的错误请求总数

最佳实践

1. 选择合适的速率限制类型

  • 使用本地速率限制进行单实例保护
  • 使用全局速率限制进行分布式保护
  • 结合使用两种类型

2. 合理设置限制

  • 根据服务容量设置限制
  • 考虑业务峰值需求
  • 定期调整限制参数

3. 监控和告警

  • 监控速率限制指标
  • 设置适当的告警阈值
  • 分析限速模式

注意事项

  • 速率限制会影响用户体验
  • 需要平衡保护和服务可用性
  • 配置变更需要谨慎测试
  • 考虑限速的副作用

速率限制是 Envoy 中重要的流量控制功能,合理配置可以有效保护服务免受过载。

文章导航

章节内容

这是章节的内容页面。

章节概览