# 接口限流

SOP提供了简单的接口限流策略：

- 漏桶策略：每秒处理固定数量的请求，超出请求返回错误信息。
- 令牌桶策略：每秒放置固定数量的令牌数，每个请求进来后先去拿令牌，拿到了令牌才能继续，拿不到则等候令牌重新生成了再拿。

如果一个接口设置了漏桶策略，假设接口每秒可处理5个请求，一秒内同时有6个请求进来，前5个接口是能够访问的，第六个请求将返回错误信息。

如果设置了令牌桶策略，桶的容量是5，那么每秒中生成5个令牌，同一时间有6个请求进来，那么前5个能成功拿到令牌继续，第六个则等待，令牌重新生成了再拿。

默认情况下接口的限流功能是关闭的，可在sop admin中配置并开启。功能在`路由管理-->限流管理`下。

## 新版限流（1.9.0）

1.9.0将之前的限流进行了改造，新的限流支持更多的限流方式。之前只能针对某个接口限流，新版限流可以在`路由ID（接口）、appKey、ip`上进行限流。

- 可针对接口进行限流，所有访问该接口的请求都被限流
- 可针对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/api?method=goods.get&app_key=xxxx`，客户端IP为`172.1.2.2`

这种情况下上面三条限流规则都命中了，由于排序值小优先执行，因此第二条规则命中.


具体设置方式可在sop admin中配置，功能在`服务管理-->限流管理`下。执行`sop-test/src/test/java/com/gitee/sop/LimitDemoPostTest.java`测试用例验证限流情况

![限流配置](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
```

- ZuulConfig.java中添加如下代码：

```java
@Autowired
private RedisTemplate redisTemplate;

@Override
protected void doAfter() {
    super.doAfter();
    ApiConfig.getInstance().setLimitManager(new RedisLimitManager(redisTemplate));
}
```

