场景:例如A服务能够处理每秒200个请求。如果B系统调用A系统的请求频率超过这个频率,A服务器就可能会挂掉。我们可以对A服务器做限流。
常见的限流技术主要分为:nginx限流,后端Tomcat服务器限流,后端服务器技术限流(漏桶算法,令牌桶)
tomcat限流
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
maxThreads="150"
redirectPort="8443" />
在tomcat的config文件夹下有maxThreads 就是 Tomcat 的最大线程数,当请求的并发大于此值(maxThreads)时,请求就会排队执行,这样就完成了限流的目的。
nginx限流
Nginx 提供了两种限流手段:一是控制速率,二是控制并发连接数。
控制速率
我们需要使用 limit_req_zone 用来限制单位时间内的请求数,即速率限制。
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s;
server {
location / {
limit_req zone=mylimit;
}
}
限制每个 IP 访问的速度为 2r/s,因为 Nginx 的限流统计是基于毫秒的,我们设置的速度是 2r/s,转换一下就是 500ms 内单个 IP 只允许通过 1 个请求,从 501ms 开始才允许通过第 2 个请求。
控制并发数
利用 limit_conn_zone 和 limit_conn 两个指令即可控制并发数
其中 limit_conn perip 10 表示限制单个 IP 同时最多能持有 10 个连接;limit_conn perserver 100 表示 server 同时能处理并发连接的总数为 100 个。
后台服务器限流技术
漏桶算法
算法思路:水(请求)先进入漏桶里,漏桶以恒定的速度流出,当流出的速度大于进入的速度,就会溢出,可以看出漏桶算法限制数据传输的速度。
漏桶算法的实现步骤是,先声明一个队列用来保存请求,这个队列相当于漏斗,当队列容量满了之后就放弃新来的请求,然后重新声明一个线程定期从任务队列中获取一个或多个任务进行执行,这样就实现了漏桶算法。
redis提供了 Redis-Cell 模块。
15:是max_burst,就是初始时,最大的容量,就是令牌桶初始时的数量,但是初始化数量是该值加一。
30/60 ;漏斗滴水的速率。 在指定时间内窗口内允许访问的次数
apply 1 token 获取的令牌
令牌桶
令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。
依赖
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.1-jre</version>
</dependency>
java代码
RateLimiter limiter = RateLimiter.create(1000);
@RequestMapping("/hello")
public String hello(){
String result = "";
boolean tryAcquire = limiter.tryAcquire(1000, TimeUnit.MILLISECONDS);
if(!tryAcquire){
result = "被限流了服务降级";
return result;
}
result = sqlService.sayHello();
return result;
}