高并发之限流

#

高并发之限流

现在常用的系统对外接口一般而言都是json或者字符读取和返回的,只有银行以及部分大型项目才会用到8583字节流,但是二者在使用的过程中都是出现流量峰值,或者简单点说就是系统处理能力的峰值,数据库的峰值,达到这个峰值系统或者数据库就有崩溃的可能。系统或者数据库一旦崩溃就是一个非常麻烦的事情,所以在持续性高并发的系统中我们就会用到高兵发的限流操作;限流基本都是为了保护系统:缓存、降级和限流。

缓存:
缓存比较好理解,在大型高并发系统中,如果没有缓存数据库将分分钟被爆,系统也会瞬间瘫痪。使用缓存不单单能够提升系统访问速度、提高并发访问量,也是保护数据库、保护系统的有效方式。大型网站一般主要是“读”,缓存的使用很容易被想到。在大型“写”系统中,缓存也常常扮演者非常重要的角色。比如累积一些数据批量写入,内存里面的缓存队列(生产消费),以及HBase写数据的机制等等也都是通过缓存提升系统的吞吐量或者实现系统的保护措施。甚至消息中间件,你也可以认为是一种分布式的数据缓存。

降级:
服务降级是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。降级往往会指定不同的级别,面临不同的异常等级执行不同的处理。根据服务方式:可以拒接服务,可以延迟服务,也有时候可以随机服务。根据服务范围:可以砍掉某个功能,也可以砍掉某些模块。总之服务降级需要根据不同的业务需求采用不同的降级策略。主要的目的就是服务虽然有损但是总比没有好。

限流:
限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量已达到保护系统的目的。一般来说系统的吞吐量是可以被测算的,为了保证系统的稳定运行,一旦达到的需要限制的阈值,就需要限制流量并采取一些措施以完成限制流量的目的。比如:延迟处理,拒绝处理,或者部分拒绝处理等等。

限流的算法:
常见的限流算法有:计数器、漏桶和令牌桶算法。

其中计数器的方法是最简单粗暴的方法,计数器。比如某个服务最多只能每秒钟处理100个请求。我们可以设置一个1秒钟的滑动窗口,窗口中有10个格子,每个格子100毫秒,每100毫秒移动一次,每次移动都需要记录当前服务请求的次数。内存中需要保存10次的次数。可以用数据结构LinkedList来实现。格子每次移动的时候判断一次,当前访问次数和LinkedList中最后一个相差是否超过100,如果超过就需要限流了。
高并发之限流_第1张图片
很明显,当滑动窗口的格子划分的越多,那么滑动窗口的滚动就越平滑,限流的统计就会越精确。

漏桶算法
漏桶算法即leaky bucket是一种非常常用的限流算法,可以用来实现流量整形(Traffic Shaping)和流量控制(Traffic Policing)。简单点说就是我们把可容许的流量或者峰值作为一个水桶,桶底部有一个小洞,这个洞能漏出去的水是固定,当请求不多的时候能够正常处理,但是当进入的请求多了,桶里面的水就流出去了,不能在接收这些请求,这些请求就只能被放弃掉了。

令牌桶算法

令牌桶算法是一个存放固定容量令牌(token)的桶,按照固定速率往桶里添加令牌。令牌桶算法基本可以用下面的几个概念来描述:

令牌将按照固定的速率被放入令牌桶中。比如每秒放10个。
桶中最多存放b个令牌,当桶满时,新添加的令牌被丢弃或拒绝。
当一个n个字节大小的数据包到达,将从桶中删除n个令牌,接着数据包被发送到网络上。
如果桶中的令牌不足n个,则不会删除令牌,且该数据包将被限流(要么丢弃,要么缓冲区等待)。
如下图:
高并发之限流_第2张图片

令牌算法是根据放令牌的速率去控制输出的速率,也就是上图的to network的速率。to network我们可以理解为消息的处理程序,执行某段业务或者调用某个RPC。

漏桶和令牌桶的比较

令牌桶可以在运行时控制和调整数据处理的速率,处理某时的突发流量。放令牌的频率增加可以提升整体数据处理的速度,而通过每次获取令牌的个数增加或者放慢令牌的发放速度和降低整体数据处理速度。而漏桶不行,因为它的流出速率是固定的,程序处理速度也是固定的。

整体而言,令牌桶算法更优,但是实现更为复杂一些。

在实际应用中我们一般会选择首先通过域名将流量流向指定的中转机或者路由机,这个中转机可以是Nginx或者路由器组成的分流系统,然后每台Nginx在会将不同的请求根据不同服务器的权重划分到不同的服务器上,由服务器来处理,当达到一定的峰值后,常见的处理方式有两种:

1.路由直接将溢出的请求包丢掉
2.系统过滤掉处理不了的请求,直接给客户端截流或者丢包
这样就可以达到系统的要求了

你可能感兴趣的:(并发,限流,高并发)