![2ad6fbaa460d253f8d54bf980c473725.png](https://img-blog.csdnimg.cn/img_convert/2ad6fbaa460d253f8d54bf980c473725.png)
为什么需要限流?
在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流。限流可以认为服务降级的一种,限流通过限制请求的流量以达到保护系统的目的。
一般来说,系统的吞吐量是可以计算出一个阈值的,为了保证系统的稳定运行,一旦达到这个阈值,就需要限制流量并采取一些措施以完成限制流量的目的。比如:延迟处理,拒绝处理,或者部分拒绝处理等等。否则,很容易导致服务器的宕机。
现有的方案
Google的Guava工具包中就提供了一个限流工具类——RateLimiter,本文也是通过使用该工具类来实现限流功能。RateLimiter是基于“令牌通算法”来实现限流的。
令牌桶算法
令牌桶算法是一个存放固定容量令牌(token)的桶,按照固定速率往桶里添加令牌。令牌桶算法基本可以用下面的几个概念来描述:
- 假如用户配置的平均发送速率为r,则每隔1/r秒一个令牌被加入到桶中。
- 桶中最多存放b个令牌,当桶满时,新添加的令牌被丢弃或拒绝。
- 当一个n个字节大小的数据包到达,将从桶中删除n个令牌,接着数据包被发送到网络上。
- 如果桶中的令牌不足n个,则不会删除令牌,且该数据包将被限流(要么丢弃,要么缓冲区等待)。
限流器实现
1.pom文件中引入Guava包
<dependency>
2.自定义拦截器,并在拦截器中实现限流
a)定义一个拦截器抽象类,用于多个拦截器复用,主要是继承HandlerInterceptorAdapter,重写preHandle方法;并提供preFilter抽象方法,供子类实现。
![74959a7be78bb171c2cbdbbe75be22d6.png](https://img-blog.csdnimg.cn/img_convert/74959a7be78bb171c2cbdbbe75be22d6.png)
b)定义流量控制拦截器,流量控制拦截器继承自上面的拦截器抽象类,在preFilter方法中进行流量控制。
@Component
使用Guava提供的RateLimiter类来实现流量控制,过程很简单:定义了一个QPS为1的全局限流器(便于测试),使用tryAcquire()方法来尝试获取令牌,如果成功则返回ResponseEnum.OK,否则返回ResponseEnum.RATE_LIMIT。
3.继承WebMvcConfigurerAdapter来添加自定义拦截器
![b0d8641821cf2667f35358e9114faff1.png](https://img-blog.csdnimg.cn/img_convert/b0d8641821cf2667f35358e9114faff1.png)
4.写一个Controller来提供一个简单的访问接口
@Controller
上文使用到的ResponseEnum是一个返回Code的枚举:
![e4e7db99900d66ae62813ea21418ea29.png](https://img-blog.csdnimg.cn/img_convert/e4e7db99900d66ae62813ea21418ea29.png)
所有文件的目录结构如下:
![38bebe21f0f1cc9591eb3e774cd825cb.png](https://img-blog.csdnimg.cn/img_convert/38bebe21f0f1cc9591eb3e774cd825cb.png)
5.使用Postman来测试接口
快速并且反复的调用接口,可以很容易的看到两种结果。
成功通过限流器的结果:
![84a09ccc3caba0ae64dfcb12a1af04ea.png](https://img-blog.csdnimg.cn/img_convert/84a09ccc3caba0ae64dfcb12a1af04ea.png)
没有成功通过限流器的返回结果:
![ec1e44ae95625e04c34de7d2ca698afe.png](https://img-blog.csdnimg.cn/img_convert/ec1e44ae95625e04c34de7d2ca698afe.png)
反复调用时,Console输出如下:
![f61a740e77ac04d9433c28ef5e71f11d.png](https://img-blog.csdnimg.cn/img_convert/f61a740e77ac04d9433c28ef5e71f11d.png)
至此,简单的限流器实现完成。
错误情况
如果在测试时,出现以下错误。
![d2e633cafb62d3ad841ba553fe4a30ce.png](https://img-blog.csdnimg.cn/img_convert/d2e633cafb62d3ad841ba553fe4a30ce.png)
解决:在pom依赖中添加以下jar包即可解决。
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.3</version>
</dependency>
推荐阅读
程序员囧辉:字节、美团、快手核心部门面试总结(真题解析)zhuanlan.zhihu.com![f386c8ef14777764244447bfb6063532.png](https://img-blog.csdnimg.cn/img_convert/f386c8ef14777764244447bfb6063532.png)
![6300261d7406e701a65cfa9c3602229f.png](https://img-blog.csdnimg.cn/img_convert/6300261d7406e701a65cfa9c3602229f.png)
![da64a845241052ca8d42dee4bd787cc6.png](https://img-blog.csdnimg.cn/img_convert/da64a845241052ca8d42dee4bd787cc6.png)
![6300261d7406e701a65cfa9c3602229f.png](https://img-blog.csdnimg.cn/img_convert/6300261d7406e701a65cfa9c3602229f.png)
![f386c8ef14777764244447bfb6063532.png](https://img-blog.csdnimg.cn/img_convert/f386c8ef14777764244447bfb6063532.png)