请求限流
用于限制接口在一段时间之内的请求次数,整体功能分为gateway限流和mvc服务限流,其中:
- gateway通过配置实现限流
- mvc服务可以通过配置或者配置加注解的方式进行限流
网关限流
适用于网关gateway的限流组件,通过配置实现接口限流。
如需获取网关限流能力,请确保网关服务依赖了以下组件:
<dependency>
<groupId>com.ikingtech.framework</groupId>
<artifactId>sdk-limit-gateway</artifactId>
</dependency>
如需开启网关限流功能,请添加以下配置:
iking:
framework:
rate-limit:
enable: true #限流开关,默认关闭
cacheKeyPrefix: rate_limit #限流缓存key前缀,默认为rate_limit
time: 60 #默认60,单位s
count: 100 #默认100,代表次数
exclude-list: #此处代表需要放行的接口集合,当请求方式和请求地址匹配时对接口放行
- type: post #请求方式,大小写不敏感,支持:get、post、delete、put,下方type同理
uri: /server/system/variable/** #请求地址:此处配置写在网关处,需要以服务名开头,支持路径通配符,下方配置中uri同理
include-list: #此处代表需要限流的接口集合,为空时对所有经过网关且不在excludeList中的接口进行限流操作
- type: post #同上方type
uri: /server/system/menu/** #同上方uri
time: 60 #具体接口的限流时间,单位s,此处不指定的话以上级的time为准
count: 10 #具体接口的限流次数,此处不指定的话以上级的count为准
在服务pom文件中引入限流组件坐标并在yml配置文件中开启限流(enable: true),配置好需要限流(include-list)和放行(exclude-list)的接口即可。
服务限流
适用于一般的SpringBoot服务的限流组件,通过配置和注解方式实现接口限流。
如需获取服务限流能力,请确保服务依赖了以下组件:
<dependency>
<groupId>com.ikingtech.framework</groupId>
<artifactId>sdk-limit-mvc</artifactId>
</dependency>
如需开启网关限流功能,请添加以下配置:
iking:
framework:
rate-limit:
enable: true #限流开关,默认关闭
cacheKeyPrefix: rate_limit #限流缓存key前缀,默认为rate_limit
priority: cover #优先级,默认为complement
time: 60 #默认60,单位s
count: 100 #默认100,代表次数
exclude-list: #此处代表需要放行的接口集合,当请求方式和请求地址匹配时对接口放行
- type: post #请求方式,大小写不敏感,支持:get、post、delete、put,下方type同理
uri: /server/system/variable/** #请求地址:此处配置写在网关处,需要以服务名开头,支持路径通配符,下方配置中uri同理
include-list: #此处代表需要限流的接口集合,为空时对所有经过网关且不在excludeList中的接口进行限流操作
- type: post #同上方type
uri: /server/system/menu/** #同上方uri
time: 60 #具体接口的限流时间,单位s,此处不指定的话以上级的time为准
count: 10 #具体接口的限流次数,此处不指定的话以上级的count为准
相较于gateway的限流,mvc的限流多了一个优先级模式(priority),共有两个选项:覆盖、补充。
- 覆盖(cover):指完全按照配置中的规则对接口进行限流操作
- 补充(complement):指按照配置和注解的方式对接口进行限流操作,当配置和注解冲突时,配置优先
服务限流使用方法
在服务pom文件中引入maven坐标,并在配置文件中开启限流(enable: true),配置好优先级模式。然后在服务中的Conrtroller中对需要限流的接口添加注解:
import com.ikingtech.framework.sdk.limit.api.annotation.RateLimiter;
@RateLimiter(count = 10, time = 100)
public R<String> saveOrUpdate(T t) {
return R.ok(service.saveOrUpdate(t));
}
或者在配置文件中指定需要限流(include-list)和放行(exclude-list)的接口。
实现原理
基于redis + lua脚本实现接口限流
key的值在gateway中为通用前缀 + 服务名 + 服务器ip地址 + 端口 + 请求路径
rate_limit:gateway:192.168.2.172:8000/server/system/variable/list/page
在mvc服务中为通用前缀 + 服务名 + 服务器ip地址 + 端口 + 请求路径
rate_limit:server:192.168.2.172:6000/system/variable/list/page
value为本次接口的请求次数,并对该key设置过期时间。过期时间来自于配置或者接口中的time字段,然后对于需要限流的接口在lua脚本中进行判断,在过期时间内如果请求次数大于设置的count,则对请求进行返回。
注意
如果只希望指定放行接口,请显式指定include-list为空,比如这样:
iking:
framework:
rate-limit:
enable: true
time: 60
count: 100
exclude-list:
- type: post
uri: /server/system/variable/**
include-list:
这段配置表示只对server服务下的/system/variable下的请求方式为post的接口进行放行,其他接口均执行限流操作,限流时间段为60s,次数为100次。
这样写的原因是因为在下述这种场景下会导致include-list没有被清空,造成与预期不符的限流效果。
反例:第一次启动服务时nacos中的配置:
iking:
framework:
rate-limit:
enable: true
time: 60
count: 100
include-list:
- type: post
uri: /server/system/variable/**
这段配置的意思是打开限流并只对server服务下的/system/variable路径下的请求方式为post的请求限流
启动服务后在nacos中修改配置为如下:
iking:
framework:
rate-limit:
enable: true
time: 60
count: 100
exclude-list:
- type: post
uri: /server/system/menu/**
这段配置的意思是打开限流并只对server服务下的/system/menu路径下的请求方式为post的请求放行
在不重启服务的情况下,此时程序运行时的配置中依然有第一次配置中的includeList的配置,依然会对第一次配置中的接口进行限流操作,而这与我们的预期是不符的,所以我们在不希望重启服务的情况下进行配置时需要明确的指定哪些接口需要放行和限流。