-
Notifications
You must be signed in to change notification settings - Fork 436
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add plugin: ai-token-ratelimit (#1015)
- Loading branch information
Showing
7 changed files
with
904 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
main.wasm | ||
config.yaml |
186 changes: 186 additions & 0 deletions
186
plugins/wasm-go/extensions/ai-token-ratelimit/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
# 功能说明 | ||
|
||
`ai-token-ratelimit`插件实现了基于特定键值实现token限流,键值来源可以是 URL 参数、HTTP 请求头、客户端 IP 地址、consumer 名称、cookie中 key 名称 | ||
|
||
|
||
|
||
# 配置说明 | ||
|
||
| 配置项 | 类型 | 必填 | 默认值 | 说明 | | ||
| ----------------------- | ------ | ---- | ------ |---------------------------------------------------------------------------| | ||
| rule_name | string | 是 | - | 限流规则名称,根据限流规则名称+限流类型+限流key名称+限流key对应的实际值来拼装redis key | | ||
| rule_items | array of object | 是 | - | 限流规则项,按照rule_items下的排列顺序,匹配第一个rule_item后命中限流规则,后续规则将被忽略 | | ||
| rejected_code | int | 否 | 429 | 请求被限流时,返回的HTTP状态码 | | ||
| rejected_msg | string | 否 | Too many requests | 请求被限流时,返回的响应体 | | ||
| redis | object | 是 | - | redis相关配置 | | ||
|
||
`rule_items`中每一项的配置字段说明 | ||
|
||
| 配置项 | 类型 | 必填 | 默认值 | 说明 | | ||
| --------------------- | --------------- | -------------------------- | ------ | ------------------------------------------------------------ | | ||
| limit_by_header | string | 否,`limit_by_*`中选填一项 | - | 配置获取限流键值的来源 HTTP 请求头名称 | | ||
| limit_by_param | string | 否,`limit_by_*`中选填一项 | - | 配置获取限流键值的来源 URL 参数名称 | | ||
| limit_by_consumer | string | 否,`limit_by_*`中选填一项 | - | 根据 consumer 名称进行限流,无需添加实际值 | | ||
| limit_by_cookie | string | 否,`limit_by_*`中选填一项 | - | 配置获取限流键值的来源 Cookie中 key 名称 | | ||
| limit_by_per_header | string | 否,`limit_by_*`中选填一项 | - | 按规则匹配特定 HTTP 请求头,并对每个请求头分别计算限流,配置获取限流键值的来源 HTTP 请求头名称,配置`limit_keys`时支持正则表达式或`*` | | ||
| limit_by_per_param | string | 否,`limit_by_*`中选填一项 | - | 按规则匹配特定 URL 参数,并对每个参数分别计算限流,配置获取限流键值的来源 URL 参数名称,配置`limit_keys`时支持正则表达式或`*` | | ||
| limit_by_per_consumer | string | 否,`limit_by_*`中选填一项 | - | 按规则匹配特定 consumer,并对每个 consumer 分别计算限流,根据 consumer 名称进行限流,无需添加实际值,配置`limit_keys`时支持正则表达式或`*` | | ||
| limit_by_per_cookie | string | 否,`limit_by_*`中选填一项 | - | 按规则匹配特定 Cookie,并对每个 Cookie 分别计算限流,配置获取限流键值的来源 Cookie中 key 名称,配置`limit_keys`时支持正则表达式或`*` | | ||
| limit_by_per_ip | string | 否,`limit_by_*`中选填一项 | - | 按规则匹配特定 IP,并对每个 IP 分别计算限流,配置获取限流键值的来源 IP 参数名称,从请求头获取,以`from-header-对应的header名`,示例:`from-header-x-forwarded-for`,直接获取对端socket ip,配置为`from-remote-addr` | | ||
| limit_keys | array of object | 是 | - | 配置匹配键值后的限流次数 | | ||
|
||
`limit_keys`中每一项的配置字段说明 | ||
|
||
| 配置项 | 类型 | 必填 | 默认值 | 说明 | | ||
| ---------------- | ------ | ------------------------------------------------------------ | ------ | ------------------------------------------------------------ | | ||
| key | string | 是 | - | 匹配的键值,`limit_by_per_header`,`limit_by_per_param`,`limit_by_per_consumer`,`limit_by_per_cookie` 类型支持配置正则表达式(以regexp:开头后面跟正则表达式)或者*(代表所有),正则表达式示例:`regexp:^d.*`(以d开头的所有字符串);`limit_by_per_ip`支持配置 IP 地址或 IP 段 | | ||
| token_per_second | int | 否,`token_per_second`,`token_per_minute`,`token_per_hour`,`token_per_day` 中选填一项 | - | 允许每秒请求token数 | | ||
| token_per_minute | int | 否,`token_per_second`,`token_per_minute`,`token_per_hour`,`token_per_day` 中选填一项 | - | 允许每分钟请求token数 | | ||
| token_per_hour | int | 否,`token_per_second`,`token_per_minute`,`token_per_hour`,`token_per_day` 中选填一项 | - | 允许每小时请求token数 | | ||
| token_per_day | int | 否,`token_per_second`,`token_per_minute`,`token_per_hour`,`token_per_day` 中选填一项 | - | 允许每天请求token数 | | ||
|
||
`redis`中每一项的配置字段说明 | ||
|
||
| 配置项 | 类型 | 必填 | 默认值 | 说明 | | ||
| ------------ | ------ | ---- | ---------------------------------------------------------- | --------------------------- | | ||
| service_name | string | 必填 | - | redis 服务名称,带服务类型的完整 FQDN 名称,例如 my-redis.dns、redis.my-ns.svc.cluster.local | | ||
| service_port | int | 否 | 服务类型为固定地址(static service)默认值为80,其他为6379 | 输入redis服务的服务端口 | | ||
| username | string | 否 | - | redis用户名 | | ||
| password | string | 否 | - | redis密码 | | ||
| timeout | int | 否 | 1000 | redis连接超时时间,单位毫秒 | | ||
|
||
|
||
|
||
# 配置示例 | ||
|
||
## 识别请求参数 apikey,进行区别限流 | ||
|
||
```yaml | ||
rule_name: default_rule | ||
rule_items: | ||
- limit_by_param: apikey | ||
limit_keys: | ||
- key: 9a342114-ba8a-11ec-b1bf-00163e1250b5 | ||
token_per_minute: 10 | ||
- key: a6a6d7f2-ba8a-11ec-bec2-00163e1250b5 | ||
token_per_hour: 100 | ||
- limit_by_per_param: apikey | ||
limit_keys: | ||
# 正则表达式,匹配以a开头的所有字符串,每个apikey对应的请求10qds | ||
- key: "regexp:^a.*" | ||
token_per_second: 10 | ||
# 正则表达式,匹配以b开头的所有字符串,每个apikey对应的请求100qd | ||
- key: "regexp:^b.*" | ||
token_per_minute: 100 | ||
# 兜底用,匹配所有请求,每个apikey对应的请求1000qdh | ||
- key: "*" | ||
token_per_hour: 1000 | ||
redis: | ||
service_name: redis.static | ||
``` | ||
|
||
|
||
|
||
## 识别请求头 x-ca-key,进行区别限流 | ||
|
||
```yaml | ||
rule_name: default_rule | ||
rule_items: | ||
- limit_by_header: x-ca-key | ||
limit_keys: | ||
- key: 102234 | ||
token_per_minute: 10 | ||
- key: 308239 | ||
token_per_hour: 10 | ||
- limit_by_per_header: x-ca-key | ||
limit_keys: | ||
# 正则表达式,匹配以a开头的所有字符串,每个apikey对应的请求10qds | ||
- key: "regexp:^a.*" | ||
token_per_second: 10 | ||
# 正则表达式,匹配以b开头的所有字符串,每个apikey对应的请求100qd | ||
- key: "regexp:^b.*" | ||
token_per_minute: 100 | ||
# 兜底用,匹配所有请求,每个apikey对应的请求1000qdh | ||
- key: "*" | ||
token_per_hour: 1000 | ||
redis: | ||
service_name: redis.static | ||
``` | ||
|
||
|
||
|
||
## 根据请求头 x-forwarded-for 获取对端IP,进行区别限流 | ||
|
||
```yaml | ||
rule_name: default_rule | ||
rule_items: | ||
- limit_by_per_ip: from-header-x-forwarded-for | ||
limit_keys: | ||
# 精确ip | ||
- key: 1.1.1.1 | ||
token_per_day: 10 | ||
# ip段,符合这个ip段的ip,每个ip 100qpd | ||
- key: 1.1.1.0/24 | ||
token_per_day: 100 | ||
# 兜底用,即默认每个ip 1000qpd | ||
- key: 0.0.0.0/0 | ||
token_per_day: 1000 | ||
redis: | ||
service_name: redis.static | ||
``` | ||
|
||
## 识别consumer,进行区别限流 | ||
|
||
```yaml | ||
rule_name: default_rule | ||
rule_items: | ||
- limit_by_consumer: '' | ||
limit_keys: | ||
- key: consumer1 | ||
token_per_second: 10 | ||
- key: consumer2 | ||
token_per_hour: 100 | ||
- limit_by_per_consumer: '' | ||
limit_keys: | ||
# 正则表达式,匹配以a开头的所有字符串,每个consumer对应的请求10qds | ||
- key: "regexp:^a.*" | ||
token_per_second: 10 | ||
# 正则表达式,匹配以b开头的所有字符串,每个consumer对应的请求100qd | ||
- key: "regexp:^b.*" | ||
token_per_minute: 100 | ||
# 兜底用,匹配所有请求,每个consumer对应的请求1000qdh | ||
- key: "*" | ||
token_per_hour: 1000 | ||
redis: | ||
service_name: redis.static | ||
``` | ||
|
||
|
||
|
||
## 识别cookie中的键值对,进行区别限流 | ||
|
||
```yaml | ||
rule_name: default_rule | ||
rule_items: | ||
- limit_by_cookie: key1 | ||
limit_keys: | ||
- key: value1 | ||
token_per_minute: 10 | ||
- key: value2 | ||
token_per_hour: 100 | ||
- limit_by_per_cookie: key1 | ||
limit_keys: | ||
# 正则表达式,匹配以a开头的所有字符串,每个cookie中的value对应的请求10qds | ||
- key: "regexp:^a.*" | ||
token_per_second: 10 | ||
# 正则表达式,匹配以b开头的所有字符串,每个cookie中的value对应的请求100qd | ||
- key: "regexp:^b.*" | ||
token_per_minute: 100 | ||
# 兜底用,匹配所有请求,每个cookie中的value对应的请求1000qdh | ||
- key: "*" | ||
token_per_hour: 1000 | ||
rejected_code: 200 | ||
rejected_msg: '{"code":-1,"msg":"Too many requests"}' | ||
redis: | ||
service_name: redis.static | ||
``` |
Oops, something went wrong.