本文介绍了流量控制插件的配置及常见场景示例。
1. 概述
流量控制插件用于对API进行限流,流量控制插件可以对
API
,App(访问的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 创建流控插件数据集
登录API网关控制台,左侧栏单击开放API——插件管理——自定义数据集。
单击右上角的创建数据集,在弹出框中自定义数据集的名称,类型选择TRAFFIC_CONTROL_POLICY,单击确定即可生成数据集。
进入刚生成的数据集,单击右上角的创建数据集条目,即可在页面中配置流控插件支持的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
(必选):流控插件的作用范围,支持API
,PLUGIN
两种取值,如果多个API都绑定了同一个插件,则scope
的取值会影响流控策略的作用范围,比如:某个策略取值为10次/秒
。当取值为
API
时:流控策略在每个API中分别生效,在本例子中,每个API的限流均为10次/秒
当取值为
PLUGIN
时:所有绑定了本插件的API共享这个限流,如果本例子中的插件绑定了一堆API,则这一堆API的总流控限制为10次/秒
parameters
(必选):参与流控的参数表,参考参数与条件表达式的使用文档中的描述rules
(可选):流控策略的列表,如果没有设置默认流控defaultLimit
与period
, 则不能为空,每个流控策略包含以下字段: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请求方法 (大写),如: |
Path | 请求 | HTTP完整请求路径,如: |
Header | 请求 | 使用 |
Query | 请求 | 使用 |
Form | 请求 | 使用 |
Host | 请求 | 使用 |
Parameter | 请求 | 使用 |
System | 请求 | 使用 |
Token | 请求 | 当处于 |
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。