|
|
|
# 接口限流
|
|
|
|
|
|
|
|
SOP提供了简单的接口限流策略:
|
|
|
|
|
|
|
|
- 窗口策略:每秒处理固定数量的请求,超出请求返回错误信息。
|
|
|
|
- 令牌桶策略:每秒放置固定数量的令牌数,每个请求进来后先去拿令牌,拿到了令牌才能继续,拿不到则等候令牌重新生成了再拿。
|
|
|
|
|
|
|
|
如果一个接口设置了窗口策略,假设接口每秒可处理5个请求,一秒内同时有6个请求进来,前5个接口是能够访问的,第六个请求将返回错误信息。
|
|
|
|
|
|
|
|
如果设置了令牌桶策略,桶的容量是5,那么每秒中生成5个令牌,同一时间有6个请求进来,那么前5个能成功拿到令牌继续,第六个则等待,令牌重新生成了再拿。
|
|
|
|
|
|
|
|
默认情况下接口的限流功能是关闭的,可在sop admin中配置并开启。功能在`路由管理-->限流管理`下。
|
|
|
|
|
|
|
|
## 多维度限流
|
|
|
|
|
|
|
|
- 可针对接口进行限流,所有访问该接口的请求都被限流
|
|
|
|
- 可针对appKey进行限流,某个appKey请求过来后,对他限流
|
|
|
|
- 可针对IP进行限流,某个IP请求过来后,对他限流
|
|
|
|
|
|
|
|
此外还可以进行组合
|
|
|
|
|
|
|
|
- 可针对接口+appKey进行限流,这个appKey调用某个接口比较频繁,可以将它限制住
|
|
|
|
- 可针对接口+IP进行限流,某个ip在频繁调用接口,可以将它限制住
|
|
|
|
|
|
|
|
由于存在组合情况,一个接口可能会配置多个限流规则。在这种情况下会优先取排序值小的那一条,如果排序值一样,则默认取第一条。
|
|
|
|
|
|
|
|
假设有下面几个限流规则:
|
|
|
|
|
|
|
|
- 接口:`goods.get`, 排序值:1, 每秒可处理请求数:10
|
|
|
|
- 接口:`goods.get`, appKey:xxxx, 排序值:0, 每秒可处理请求数:5
|
|
|
|
- 接口:`goods.get`, ip:172.1.2.2, 排序值:2, 每秒可处理请求数:6
|
|
|
|
|
|
|
|
客户端调用接口:`http://open.domain.com?method=goods.get&app_id=xxxx`,客户端IP为`172.1.2.2`
|
|
|
|
|
|
|
|
这种情况下上面三条限流规则都命中了,由于排序值小优先执行,因此第二条规则命中.
|
|
|
|
|
|
|
|
|
|
|
|
具体设置方式可在sop admin中配置,功能在`服务管理-->限流管理`下。执行`com.gitee.sop.test.LimitTest`测试用例验证限流情况
|
|
|
|
|
|
|
|
![限流配置](images/10092_1.png "10092_1.png")
|
|
|
|
|
|
|
|
![限流配置](images/10092_2.png "10092_2.png")
|
|
|
|
|
|
|
|
## 分布式限流
|
|
|
|
|
|
|
|
默认的限流方式是单机的,如果要部署多台网关实例,需要使用分布式限流
|
|
|
|
|
|
|
|
SOP使用redis进行分布式限流(只支持窗口策略),操作步骤如下:
|
|
|
|
|
|
|
|
- sop-gateway/pom.xml添加redis依赖
|
|
|
|
|
|
|
|
```xml
|
|
|
|
<dependency>
|
|
|
|
<groupId>org.springframework.boot</groupId>
|
|
|
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
|
|
|
</dependency>
|
|
|
|
```
|
|
|
|
|
|
|
|
- sop-gateway下的application-dev.properties文件添加redis配置
|
|
|
|
|
|
|
|
```properties
|
|
|
|
# redis
|
|
|
|
spring.redis.database=0
|
|
|
|
spring.redis.host=127.0.0.1
|
|
|
|
spring.redis.port=6379
|
|
|
|
```
|
|
|
|
|
|
|
|
- 在`com.gitee.sop.gateway.config.MyConfig`中添加如下代码:
|
|
|
|
|
|
|
|
```java
|
|
|
|
@Autowired
|
|
|
|
private RedisTemplate redisTemplate;
|
|
|
|
|
|
|
|
@PostConstruct
|
|
|
|
public void after() {
|
|
|
|
ApiConfig.getInstance().setLimitManager(new RedisLimitManager(redisTemplate));
|
|
|
|
...
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|