10分钟带你彻底搞懂服务限流和服务降级

您所在的位置:网站首页 斗鱼限流什么意思 10分钟带你彻底搞懂服务限流和服务降级

10分钟带你彻底搞懂服务限流和服务降级

2024-07-12 08:32| 来源: 网络整理| 查看: 265

文章目录 十分钟搞懂系列服务限流计数器法滑动窗口法漏桶算法令牌桶算法 服务降级

十分钟搞懂系列 序号标题链接110分钟带你彻底搞懂企业服务总线https://blog.csdn.net/belongtocode/article/details/119487731210分钟带你彻底搞懂微内核架构https://blog.csdn.net/belongtocode/article/details/119107837310分钟带你彻底搞懂服务限流和服务降级https://blog.csdn.net/belongtocode/article/details/119107785410分钟带你彻底搞懂负载均衡https://blog.csdn.net/belongtocode/article/details/118977839510分钟带你彻底搞懂集群容错和服务隔离https://blog.csdn.net/belongtocode/article/details/118968771610分钟带你彻底搞懂注册中心https://blog.csdn.net/belongtocode/article/details/118639474710分钟带你彻底搞懂RPC架构https://blog.csdn.net/belongtocode/article/details/118639448

我们知道,在分布式系统中,当面对高并发、大流量的应用场景时,系统就会面临崩溃的风险。这时候,为了提高系统可用性,我们就需要对外部流量进行限制,以减少对现有系统的影响。目前,业界主流的两种最佳实践是服务限流和服务降级,这节课我们就来深入了解这两种解决方案。

假如你正在设计和开发一个分布式服务系统,各个服务为了满足特定业务需求,通常都会相互依赖形成一种复杂的调用链路。那么,在这样的调用链路中,服务可能因为自身无法承受大量的请求而发生调用失败,或者可能因为是该服务所依赖的其他服务出现问题而导致自身发生失败,如下所示:

img

要应对这两种失败场景,我们有两种核心的解决思路:如果是服务自身发生失败,我们希望能通过合理控制对它的请求量,降低失败的可能性,这是服务限流方案;如果是依赖的服务有问题而导致调用失败,那么就希望别的服务访问该服务时能够快速返回错误,以免导致服务依赖所产生的“雪崩效益”,也就是服务降级方案。

那么下面,我们就先来了解下限流的具体实现细节。

服务限流

顾名思义,限流的意思就是对访问服务的流量进行限制,避免高流量、尤其是突发性的高流量压垮服务。我们希望服务能通过限流,基于自身可控的速度来消费外部请求,如下图所示:

img

为了实现这个目标,业界也有一些常见的、且被实践证明可用的方法,包括用于流量控制的计数器法和滑动窗口法,以及用于流量整形的漏桶算法和令牌桶算法。

img

计数器法

基于流量计数器的限流算法的基本思想非常简单,就是控制一定时间内的请求数量,如果这个请求量能够控制在合理的访问阈值内,我们就认为能起到限流的效果。具体的实现方法,就是设置一个计数器,把来自外部的请求量都记录下来并进行统计。

我给你举个例子。假设计数器的阈值为 10,那么当单位时间内,系统累计的请求量超过了 10,我们就可以直接拒绝掉超额的部分。计数器的执行效果如下所示:

img

当然,这种做法需要在一个单位时间结束的时候,把计数器累积的请求量清零。

计数器算法可以说是限流算法里最简单也最容易实现的一种算法,但它也有一个不得不面对的问题,即临界问题,什么意思呢?

我们来想象一个场景:我们设定单位时间是 10 秒钟,阈值同样是 10。现在,假设服务请求在第 10 秒快要结束的时候,一次发送了 6 个请求,这时候一个单位时间结束,计数器清零。而在第 11 秒开始的瞬间,原则上又可以发送 8 个请求。这样在一段很短的时间内,服务 A 相当于接收到了 6+8=14 个请求,超过了限流的阈值,就可能导致服务失败。整个过程如下图所示:

img

滑动窗口法

那么面对这种情况,我们该怎么办呢?

答案是可以采用滑动窗口机制来进行限流。滑动窗口可以实现平滑的基于时间片段的统计,其本质上是把一个单位时间进行拆分,从而形成多个时间段。

比方说,我们可以把 10 秒这个单位时间划分成 10 个时间格,这样每格代表 1 秒钟。每过 1 秒钟,时间窗口就会往前滑动 1 个时间格:

img

请注意,这时候每一个时间格都有自己独立的计数器,滑动窗口能解决临界问题的关键就在这里。我们假设在第一个时间临界点,也就是第 10 秒的时候,前后各有 6 个和 8 个请求到达系统,那么当第 10 秒结束时,因为当前窗口向前滑动了一个时间格,所以这时候时间窗内的请求数量就是 6+8=14 个,超过了阈值的 10 个,从而就会触发限流机制。

从这个角度讲,滑动窗口也是一个计数器算法,只不过它的单位时间会设置得更加细化,从而能够更好地应对流量的突发性变化。

漏桶算法

讲完用于流量限制的常见做法之后,我们再来看看流量整形的两种实现方法。

我们先来看下漏桶算法。漏斗我们应该都比较熟悉,它的基本特征就是进口大、出口小,不管我们以怎样的速度往漏斗里倒入液体,但这些液体从出口流出的速率总是一样的。

这样,我们就可以把服务调用量看作是液体,那么不管服务请求的变化多么剧烈,通过漏桶算法进行整形之后,得到的就是具有固定速度的请求量:

img

从这张图中,我们能看到请求 1~9 以不同的速率进入漏桶,而输出的则是固定速率的请求 1~5,剩余的请求会继续留在漏桶。

这里你要注意,漏桶本身的容量肯定也不是无限大的,所以当请求数量超过了桶的容量,新来的请求也只能被丢弃掉了。

令牌桶算法

讲到这里,实际上我们也可以看出漏桶算法的一个缺点,因为漏桶的容量是有限的,而输出的速率又是固定的,所以当面对突发的请求流量时,我们无法有效应对流量的变化。这时候,使用令牌桶算法则是更为合适的一种选择。

令牌桶算法的结构如下图所示:

img

令牌桶算法的具体实现是这样的:我们以固定的速度将令牌放入桶中,一个令牌对应一个请求。如果在某一时间点上,桶中已经没有令牌了,那么请求就不会得到响应,而如果桶中存放着很多令牌,就可以响应很多的请求,因此服务请求的输入和输出都可以是变速的。

由此可见,和漏桶算法不一样的是,令牌桶算法应对突发流量的解决方法是允许出现动态的输出速率。

以上就是服务限流方案的实现原理,接下来我们来看看服务降级的策略。

服务降级

所谓服务降级,指的是在服务器压力剧增的情况下,根据当前业务情况及流量对一些服务执行有策略的快速失败处理,以避免服务之间的调用依赖影响到其他核心服务:

img

具体要如何实现服务降级呢?

业界的主流做法就是进行服务熔断。服务熔断的原理和电路熔断很像,我们知道在电路系统中一般都会设计一个熔断器(Circuit Breaker),确保当电流过大时能够自动切断电路。而在分布式系统中,熔断的含义就是当某一个服务已经无法正常响应请求时,其他服务就不再继续向它发起请求,以确保调用链路不会发生雪崩效应。

从设计理念上讲,当服务消费者向服务提供者发起远程调用时,服务熔断器就会监控这次调用,如果调用的响应时间过长,那么熔断器就会中断本次调用并直接返回。请注意,熔断器判断本次调用是否应该快速失败是有状态的,也就是说熔断器会把所有的调用结果都记录下来,只有发生异常的调用次数达到一定阈值,才会触发熔断机制,而不是一有异常就直接进行熔断。

img

因此,既然熔断器内部是有状态的,那我们就可以对这些状态进行抽象和提炼,从而得到如下所示的状态转换图:

img

这个状态转换的具体过程是这样的:

首先,如电路系统一样,在默认情况下熔断器都是关闭的,任何请求都会得到响应。系统会记录所有的请求处理结果,并会统计失败的调用次数,看是否已经达到了规定的熔断阈值。

然后,一旦失败调用次数到达阈值,熔断器就会打开。对于任何请求而言,都将得到失败的响应结果。请注意,这时候系统的请求处理过程是不会真正执行远程调用的,而是会执行快速失败策略。而一旦发生熔断,熔断器内部会启动一个时钟,一段时间之后就会自动进入半熔断状态。

处于半熔断状态的熔断器会允许一部分请求真正得到响应,同时也会统计调用成功的次数。如果成功的次数到达一定的数量,我们就认为系统已经恢复正常,熔断器就会关闭。而如果请求还是会不断发生错误,那么熔断器又会被重新打开。

好,以上就是这节课的主要内容。在日常开发过程中,我们可以使用服务限流和降级机制为分布系统提升服务访问的可靠性。

最后,我想给你留一道思考题:你能描述熔断器应该具备的三个状态以及它们之间的转换过程吗?你可以在评论区留下你的答案,和我讨论。

参考文章: 整理于极客时间每日一课对应文章



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3