全部产品
Search
文档中心

API 网关:流量控制插件

更新时间:Oct 29, 2024

本文介绍了流量控制插件的配置及常见场景示例。

1. 概述

  • 流量控制插件用于对API进行限流,流量控制插件可以对APIApp(访问的AK)用户(访问方的App归属用户),以及自定义参数进行多种维度的限流。

  • 流量控制插件目前支持两种配置模板:

    • 参数流控配置,支持自定义参数的流控配置。

    • 基础流控配置,与控制台上的流量控制功能保持兼容。

  • 流量控制现在合并进了插件体系。现存的流量控制界面与接口仍然可以使用,流量控制策略流量控制插件属于同一种插件类型,如果你绑定了流量控制插件,则流量控制策略会失效

  • 使用原有的流量控制接口或控制台创建或更改流量控制,会同步数据至插件系统,但不会反向同步。

2. 基础流控配置

2.1. 流控能力

2.1.1 基础流控支持以下的流控维度:

  • API 流量限制:该策略绑定的API在单位时间内被调用的次数不能超过设定值,单位时间可选秒、分钟、小时、天,如5000次/分钟。

  • APP 流量限制:每个App对该策略绑定的任何一个API在单位时间内的调用次数不能超过设定值。如50000次/小时。

  • 用户流量限制:每个阿里云账号对该策略绑定的任何一个 API 在单位时间内的调用次数不能超过设定值。一个阿里云账号可能有多个 APP,所以对阿里云账号的流量限制就是对该账号下所有 APP 的流量总和的限制。如 50 万次/天。

说明

在一个流控策略插件里面,这三个值可以同时设置。请注意,用户流量限制应不大于 API 流量限制,APP 流量限制应不大于用户流量限制。即 APP 流量限制 <= 用户流量限制 <= API 流量限制。

此外,您可以在流控策略下添加特殊应用(APP)和特殊用户。对于特例,流控策略基础的API 流量限制依然有效,您需要额外设定一个阈值作为该 APP 或者该用户的流量限制值,该值不能超过策略的API流量限制值,同时流控策略基础的APP流量限制用户流量限制对该 APP 或用户失效。

2.1.2 流控插件支持的时间维度及其算法

API网关流控插件支持的时间维度分别是秒(SENCOND)、分钟(MINUTE)、小时(HOUR)、天(DAY)。其中分钟、小时、天维度使用的是固定时间窗口算法。秒级别默认使用的是令牌桶流控算法,若不满足需求,可以配置固定时间窗口流控算法。两种算法分别如下:

  • 令牌桶流控算法:秒级别的流控默认用的是令牌桶算法。令牌桶算法有两个概念,令牌桶和一个Waiting Queue。API网关的引擎会定期向令牌桶发放令牌,客户端发送的请求进到API网关后会先去令牌桶里取令牌,取到令牌就通过了。如果没有取到令牌,请求会进一个Queue中排队,下一波发令牌的时候优先分配给Queue中请求。Queue满了之后,请求再进来就会报429;如果不想进入Queue排队,可以直接配置blockingMode: QUICK_RETURN,就不会进入Queue排队,如果没有取到令牌,直接报错429。

  • 固定时间窗口流控算法:限制单位时间的流量,例如限制每分钟1000次请求,超过部分报429,下一分钟重置请求计数。

2.2. 基础流控插件配置

可以选择JSON或者YAML格式的来配置您的插件,两种格式的schema相同,可以搜索yaml to json转换工具来进行配置格式的转换,yaml格式的模板见下表。

---
unit: SECOND         # 控制区间, 取值: SECOND, MINUTE, HOUR, DAY
apiDefault: 1000     # 允许的总流量值
controlMode: FIX_WINDOW  # 当时间维度为秒时,指定流控算法为固定时间窗口算法
blockingMode: QUICK_RETURN     #令牌桶流控算法时,不会进入Queue排队,如果没有取到令牌,直接报429
userDefault: 30      # (可选)每个用户的默认流量最大值, 0表示不进行限制, 不能大于总流量值
appDefault: 30       # (可选)每个APP允许的流量最大值, 0表示不进行限制, 不能大于总流量值
specials:            # (可选)特殊流控, 支持"APP"和"USER"两种特殊维度
  - type: "APP"      # 针对不同应用(AK)进行的流控
    policies:
    - key: 10123123  # AppId, AppId的取值请在API网关控制台->应用管理->应用详情处查看
      value: 10      # 特殊流控值, 不能大于总流量值
    - key: 10123123  # AppId控
      value: 10      # 特殊流控值, 不能大于总流量值
  - type: "USER"     # 针对不同的阿里云账户进行的流控
    policies:
    - key: 123455    # 阿里云账号ID, 可点击阿里云控制台左上角查看账号ID
      value: 100     # 特殊流控值, 不能大于总流量值

2.3 基础流控插件支持插件数据集

2.3.1 创建流控插件数据集

  1. 登录API网关控制台,左侧栏单击开放API——插件管理——自定义数据集

  2. 单击右上角的创建数据集,在弹出框中自定义数据集的名称,类型选择TRAFFIC_CONTROL_POLICY,单击确定即可生成数据集。

  3. 进入刚生成的数据集,单击右上角的创建数据集条目,即可在页面中配置流控插件支持的key和value,其中,key为AppId或阿里云账号ID;value则是对应的流控值。

2.3.2 流控插件配置插件数据集示例

基础流控插件支持使用插件数据集,特殊流控specials策略可使用插件数据集配置APP和流控值、用户阿里云账号ID和流控值。示例如下:

---
unit: SECOND         # 控制区间, 取值: SECOND, MINUTE, HOUR, DAY
apiDefault: 1000     # 允许的总流量值
userDefault: 30      # (可选)每个用户的默认流量最大值, 0表示不进行限制, 不能大于总流量值
appDefault: 30       # (可选)每个APP允许的流量最大值, 0表示不进行限制, 不能大于总流量值
specials:            # (可选)特殊流控, 支持"APP"和"USER"两种特殊维度
  - type: "APP"      # 针对不同应用(AK)进行的流控
    policyDatasetId: 87b65008e92541938XXXXXXXX6eda5		# 插件数据集ID
    policies:
    - key: 10123123  # AppId, AppId的取值请在API网关控制台->应用管理->应用详情处查看
      value: 10      # 特殊流控值, 不能大于总流量值
    - key: 10123123  # AppId控
      value: 10      # 特殊流控值, 不能大于总流量值
  - type: "USER"     # 针对不同的阿里云账户进行的流控
    policyDatasetId: 87b65008eXXXXXXXXXXXXa236eda5		# 插件数据集ID
    policies:
    - key: 123455    # 阿里云账号ID, 可点击阿里云控制台左上角查看账号ID
      value: 100     # 特殊流控值, 不能大于总流量值
重要

本次开发只针对基础配置模式的插件格式进行插件数据集的支持,对参数流控配置模式的插件配置暂不进行插件数据集的支持。

3. 参数流控配置

参数流控可以针对用户的请求参数以及条件执行进行流控,参数流控配置支持如下特性:

  • 支持秒、分钟、小时、天的流控维度

  • 可以根据请求参数、系统参数设置条件,来执行不同的流控维度

  • 可以使用单个参数、或多个参数的组合来设置流控

  • 可以设置流控的范围为API或插件

3.1. 快速开始

有这样一个场景,我们希望执行如下的规则执行流控,针对每个访问的客户端IP地址,当用户使用了AppId:10001的Key做了签名认证时,设置流控为100请求/秒,对其他的场合为10请求/秒

针对这个场景我们的插件配置如下,这里我们使用yaml来配置插件。

---
scope: "PLUGIN"
#
# 这个流控依赖两个系统参数
# 1. 用户签名的AppId,通过系统参数CaAppId获取
# 2. 用户来源的ClientIP,通过系统参数CaClientIp获取
parameters:
  AppId: "System: CaAppId"
  ClientIP: "System: CaClientIp"
rules:
  # 第一条流控策略,当`AppId`为`10001`时生效,对每个ClientIP限流为`100/秒`
  - name: "Vip"
    condition: "$AppId = 10001"
    byParameters: "ClientIP"
    value: 100
    period: SECOND
  # 第二条流控策略名为`PerClientIP`,对每个ClientIP限流为`10/秒`
  - name: "PerClientIP"
    byParameters: "ClientIP"
    bypassEmptyValue: true   #当rules中的规则没有添加condition,以byParameters参数为判断条件时,参数为空或传了空值此规则不生效,会走默认流控策略
    value: 10
    period: SECOND

3.2. 参数流控插件配置

参数流控插件使用yaml或等价的json格式进行插件元数据配置。

---
scope: "PLUGIN"                # 流控插件的作用范围:目前可选为"PLUGIN", "API"
blockingMode: QUICK_RETURN     #不会进入Queue排队,如果没有取到令牌,直接报429,详情可查看下面的字段说明
controlMode: FIX_WINDOW  # 当时间维度为秒时,指定流控算法为固定时间窗口算法
defaultLimit: 100              # 默认流控值,如果设置了默认流控值
defaultPeriod: SECOND          # 默认流控周期
defaultRetryAfterBySecond: 60  #返回Retry-After标头,它提供建议在下一个请求之前需要等待多长时间
defaultErrorMessage: "Throttled by 100/SECOND"
parameters:                    # 参数列表, 可用于流控的参数
  clientIp: "System:CaClientIp"
  userId: "Token:userId"
rules:
  - name: "ByClientIp"
    byParameters: "clientIp"
    condition: "$clientIp !in_cidr '61.7.XX.XX/24'"
    limit: 10
    period: MINUTE
    retryAfterBySecond: 60    #返回Retry-After标头,它提供建议在下一个请求之前需要等待多长时间
    errorMessage: "Throttled by 10/MINUTE from ${clientIp}"
  - name: "每个用户限制10条/分钟,管理员除外"
    byParameters: "clientIp"
    condition: "$userId !like 'admin%'"
    limit: 10
    period: MINUTE
    retryAfterBySecond: 60    #返回Retry-After标头,它提供建议在下一个请求之前需要等待多长时间
  - name: "每个IP限制10条/分钟"
    byParameters: "clientIp"
    condition: "$clientIp in_cidr '67.0.XX.XX/8'"
    limit: 10
    period: MINUTE
  - name: "每个用户限制15条/分钟"
    condition: "$userId !like 'admin%'"
    limit: 15
    period: MINUTE
    byParameters: "clientIp"

插件配置的字段说明如下:

  • scope(必选):流控插件的作用范围,支持APIPLUGIN两种取值,如果多个API都绑定了同一个插件,则scope的取值会影响流控策略的作用范围,比如:某个策略取值为10次/秒

    • 当取值为API时:流控策略在每个API中分别生效,在本例子中,每个API的限流均为10次/秒

    • 当取值为PLUGIN时:所有绑定了本插件的API共享这个限流,如果本例子中的插件绑定了一堆API,则这一堆API的总流控限制为10次/秒

  • parameters(必选):参与流控的参数表,参考参数与条件表达式的使用文档中的描述

  • rules(可选):流控策略的列表,如果没有设置默认流控defaultLimitperiod, 则不能为空,每个流控策略包含以下字段:

    • name(必选):流控策略的名称,合法值为[A-Za-z0-9_-]+,在同一个插件中保持唯一

    • byParameters(必选):流控参数,如果使用多个参数组合流控,以“,”分割,比如:ClientIP表示,针对每个ClientIP的取值分别进行流控,UserId,Action表示对这两个参数的组合取值分别进行流控

    • bypassEmptyValue(可选):值为true时,当rules中的规则没有添加condition,以byParameters参数为判断条件时,参数为空或传了空值此规则不生效,会走默认流控策略

    • condition(可选):如果设置了条件,只有当条件符合时,才会执行此条流控策略

    • limit(必选):流控值,正整数,当为-1时表示当命中此条件时不需要流控

    • period(必选): 流控周期,取值:SECOND,MINUTE,HOUR,DAY

    • errorMessage(可选):定制错误信息,可以以模板的方式来定义,在parameters中定义的参数,可以在${Name}的方式来配置

    • retryAfterBySecond(可选):返回Retry-After标头,它提供建议在下一个请求之前需要等待多长时间

  • defaultLimit(可选):默认流控值,正整数

  • defaultPeriod(可选):流控周期,取值: SECOND,MINUTE,HOUR,DAY

  • defaultErrorMessage(可选):定制错误信息,当配置了定制的错误信息后,返回的X-Ca-Error-Message头会使用定制的错误信息,这个信息无法使用参数

  • defaultRetryAfterBySecond(可选):默认返回的Retry-After标头,它提供建议在下一个请求之前需要等待多长时间。

  • blockingMode(可选):API网关使用了标准的令牌桶算法来实现流控功能,关于字段值以及算法详情如下:

    • QUEUE(默认值):令牌桶算法有两个概念:令牌桶和一个Waiting Queue。API网关的引擎会定期向令牌桶发放令牌,客户端发送的请求进到API网关后会先去令牌桶里取令牌,取到令牌就通过了。如果没有取到令牌,请求会进一个Queue中排队,下一波发令牌的时候优先分配给Queue中请求。Queue满了之后,请求再进来就会报429。

    • QUICK_RETURN:不会进入Queue排队,如果没有取到令牌,直接报429。

  • controlMode: 当时间维度为秒时,指定流控算法。默认取值TOKEN_BUCKET(令牌桶流控算法),可以配置为FIX_WINDOW(固定时间窗口流控算法 )。

3.3. 参数说明

流控插件支持以下位置的参数。

位置名称

适用范围

说明

Method

请求

HTTP请求方法 (大写),如:GET, POST ...

Path

请求

HTTP完整请求路径,如:/path/to/query

Header

请求

使用Header:{Name}获取名字为{Name}的HTTP头的第一个值

Query

请求

使用Query:{Name}获取QueryString中名字为{Name}的第一个值

Form

请求

使用Form:{Name}获取请求Form中名字为{Name}的第一个值

Host

请求

使用Host:{Name}获取匹配到的泛域名模板参数

Parameter

请求

使用Parameter:{Name}获取用户API自定义参数中名字为Name的第一个值

System

请求

使用System:{Name}获取名字为{Name}的系统参数值

Token

请求

当处于jwt,oauth2授权场景时,使用Token:{Name}获取token中名字为{Name}的值

3.4. 执行规则

API网关按照如下的顺序执行参数流控:

  • 插件会使用parameters的配置,从请求上下文中获取参数表。

  • 所有condition执行结果为true或未配置condition的策略都会被执行。

  • 如果命中策略列表中有多条策略的byParameters配置相同,则选择配置顺序靠前的那一条执行,其余的策略不会生效。

4. 配置样例

4.1. 基础流控配置样例

基础流控可支持API流控、不同AppKey、以及不同用户级别的流控。

---
unit: SECOND           # 默认的流控单位, 支持: SECOND,MINUTE,HOUR,DAY
apiDefault: 50         # API整体流控
defaultRetryAfterBySecond: 60  #默认返回Retry-After标头,它提供建议在下一个请求之前需要等待多长时间
appDefault: 20         # (可选)针对每个APP的流控值, 不大于API整体流控
userDefault: 30        # (可选)针对每个用户的流控值, 不大于API整体流控
specials:              # (可选)特殊流控, 支持"APP"和"USER"两种特殊维度
  - type: "APP"        # 针对不同应用(AppKey)进行的流控
    policies:
      - key: 10001     # AppId, AppId的取值请在API网关控制台->应用管理->应用详情处查看
        value: 3       # 特殊流控值, 不大于API整体流控
      - key: 10003
        value: 40
  - type: "USER"       # 针对不同的阿里云账户进行的流控
    policies:
      - key: 102       # 阿里云账号ID, 可点击阿里云控制台上角查看账号ID
        value: 10      # 特殊流控值, 不大于API整体流控
      - key: 233
        value: 35

4.2. 按照源IP进行参数限流

在这个例子中,我们配置了的限流策略。

  • 每个源IP允许100次/分钟的调用

  • 客户端IP处于58.66.XX.XX/24范围时,不限制访问

  • 对客户端IP为处于63.0.XX.XX,73.0.XX.XX/24范围时,访问限制为5次/天

---
scope: API             # 限流的作用范围,可选API, PLUGIN
parameters:            # 设置限流的参数,我们仅针对客户端IP进行限流, 客户端IP从系统变量`CaClientIp`中获取
  ClientIp: "System:CaClientIp"
rules:
  - name: whitelist    # 白名单策略, 当客户端IP符合条件时,不执行限流
    condition: "$ClientIp in_cidr '58.66.XX.XX/24'"
    limit: -1          # `-1`表示不进行限流
  - name: banList      # 特殊限制策略, 当客户端IP符合条件时,按照`ClientIp`参数执行每天5次的限流
    condition: "$ClientIp in_cidr '63.0.XX.XX' or $ClientIp in_cidr '73.0.XX.XX/24'"  
    byParameters: "ClientIp"
    limit: 5
    period: DAY
  - name: 100perIp     # 默认策略,每个IP,100次/分钟访问
    byParameters: "ClientIp"
    limit: 100
    period: MINUTE     # 周期,支持:SECOND, MINUTE, HOUR, DAY

4.3 防CC攻击配置

在这个例子中,我们配置如何防CC攻击。

  • 每个源IP允许3次/秒钟的调用

  • 当客户端源IP超出3次/秒钟范围时,访问将屏蔽10秒钟

---
scope: API             # 限流的作用范围,可选API, PLUGIN
defaultLimit: 3000        # 默认流控值
defaultPeriod: SECOND     # 默认流控周期
defaultRetryAfterBySecond: 60  #默认返回Retry-After标头,它提供建议在下一个请求之前需要等待多长时间
parameters:        # 设置限流的参数,我们仅针对客户端IP进行限流, 客户端IP从系统变量`CaClientIp`中获取
  clientIp: "system:CaClientIp"
rules:
  - name: "每个源IP每秒只能访问3次,一旦触及阈值,屏蔽10秒钟"
    byParameters: "clientIp"
    limit: 3
    period: SECOND
    blockingPeriodBySecond: 10     #仅专享实例生效

5. 相关错误码

错误代码

Http状态码

报错信息

描述

T429ID

429

Throttled by INNER DOMAIN Flow Control, ${Domain} is a test domain, only 1000 requests per day

当使用默认二级域名访问时,限制1000次/天(海外Region及中国香港限制100次/天),请绑定正式域名以解除这个限制

T429IN

429

Throttled by INSTANCE Flow Control

触发当前实例的流控限制

T429GR

429

Throttled by GROUP Flow Control

触发当前分组的流控限制

T429PA

429

Throttled by API Flow Control

触发插件上的默认API流控

T429PR

429

Throttled by PLUGIN Flow Control

触发插件的特殊流控

6. 使用限制

  • 参数定义个数不超过16个。

  • 单个表达式的字符数不超过512个字符。

  • 插件元数据的大小限制为50KB

  • 每个插件中rules最大不超过16条。

  • 每个rule中的byParameters最大不超过3个。

  • 当限流参数的分散度太高时,可能释放掉实际使用数据不高的数据,比如:使用了天级别的源IP流控时,系统存储了过多的流控记录时,会释放掉一部分记录,在共享实例/Serverless实例下的参数流控插件允许的不同参数个数为1000,在专享实例下的参数流控插件允许的不同参数个数为100000。