一、介绍限流前我们先来介绍几种应对服务器高并发的方案:
1,服务降级:在高并发的情况下,为了防止用户一直等待,使用服务降级方式(直接返回一个友好的提示给客户端)
2,服务熔断:熔断机制的目的是为了在高并发的情况下保护服务,当高并发的情况下,如果流量达到一定阈值后,后面的请求全部拒绝访问,起到保护服务的作用。熔断其实也是降级方式的一种
3,服务隔离:一般情况下,多个HTTP服务会共享一个线程池,假设其中一个HTTP服务访问的数据库响应非常慢,这将造成服务响应时间延迟增加,大多数线程阻塞等待数据响应返回,导致整个线程池都被该服务占用,其他多个服务都不可用,造成雪崩效应。如果我们能把不同HTTP服务隔离到不同的线程池,则某个HTTP服务的线程池满了也不会对其他服务造成灾难性故障。这就需要线服务隔离来实现。
4,服务限流:限制系统的输入和输出流量来达到保护系统的目的。一般来说系统的吞吐量是可以被测算的,为了保证系统的稳定运行,一旦达到的需要限制的阈值,就需要限制流量并采取一些措施以完成限制流量的目的。限流其实也是服务降级方式的一种,常用的算法有计数器、漏桶和令牌桶算法。
二、计数器
1,传统计数器
传统计数器是限流算法中最简单最容易的一种算法,他是通过统计一定周期内请求次数,一旦在周期内请求次数超过设置的阈值,就实现限流,当进入下一个周期后请求次数清零,如下图1分钟只接收100个请求,剩余的都做降级处理
但传统计数器会有一个临界问题,比如下图0:59时瞬间发送了100个请求,又在1:00又发送了100个请求,那么1分钟请求了200个,远远超过阈值100,起不到限流的效果
2,滑动窗口限流
如上图解决了临界问题,0:59到达的100个请求会落在灰色的格子中,而1:00到达的请求会落在橘黄色的格子中。当时间到达1:00时,我们的窗口会往右移动一格,那么此时时间窗口内的总请求数量一共是200个,超过了限定的100个,就会触发限流。但正常是1分钟100个,所以200个/min可能是系统所承受不了的,这是滑动窗口的一个缺点
三,令牌桶
如上图,令牌桶会以固定速率,比如2r/s(每秒2个)的速率往桶内存放令牌(桶内会有最大容量,最大容量代表了服务所能承受的最大并发量,以应对突然的高并发),客户端会先去桶中获取令牌,获取到了才能访问服务端,当客户端端的访问请求超过令牌的速率时,部分请求会因为获取不到令牌而触发限流,被服务降级。
四,漏桶算法
漏桶算法是流入水滴是任意速率,但流出水滴是固定速率,当流入水滴的速率>流出水滴的速率时,桶内的水就会溢出,那么溢出的这部分就会被丢弃,请求会被拒绝访问或者降级处理
缺点:在某些情况下,漏桶算法不能够有效地使用网络资源。因为漏桶算法水滴流入的时候会流入到队列中,当队列满的时候会拒绝请求,另外有一个循环以固定的速率读取数据,因为读取速率是固定的,所以即使网络中没有发生拥塞,漏桶算法也不能使某一个单独的数据流达到端口速率。因此,漏桶算法对于存在突发特性的流量来说缺乏效率。
漏桶算法和令牌桶算法的区别:漏桶算法的出水速度是恒定的,这意味着如果瞬时大流量的话,将有大部分请求被丢弃掉(也就是溢出),也无法保证高并发能快速处理流量,漏桶算法通常可以用于限制访问外部接口的流量,保护其他的系统。
令牌桶算法生成令牌的速度是恒定的,而请求去拿令牌是没有速度限制的。这意味,面对瞬时大流量,该算法可以在短时间内请求拿到大量令牌,可以处理瞬时流量,而且拿令牌的过程并不是消耗很大的事情。令牌桶算法通常可以用于限制被访问的流量,保护自身系统。