微服务限流三大件:熔断、降级、限流


写在前面

分布式系统中一般会有高负荷、异常情况,在发生这些异常情况的时候应该如何应对呢?本文介绍一些常规方法。

熔断

场景

系统负载突然过高,比如突发的访问量、过多的请求以及IO压力过载都可能会造成某个节点故障,比如节点A,然后节点A挂了,又把负载传给节点B,节点B负载过高之后又挂了,这样一连串的挂过去就会把请求从单点故障转化成为系统级别的级联故障

定义

系统里的响应时间或者异常比率或者单位异常数超过某个阈值的时候,比如超时次数或者重试次数超过某个阈值,就会触发熔断,接着所有的调用都快速失败或者返回预设的默认值,从而保证下游系统的负载安全。

在一段时间后,熔断器会尝试部分请求到目标服务,如果请求成功率高于阈值,则熔断器会逐渐闭合,恢复对目标服务的正常调用。

熔断器的状态

  • 熔断器开始处于闭合状态,如果达到触发条件,那么熔断器就会打开
  • 接着熔断器处于打开状态,所有走到这个路径里的请求会走快速失败通道,从而避免负载下行,给下游的服务造成压力,过一个时间周期之后会自动切换到半打开状态
  • 半打开状态:认为之前的错误可能已经被修复了,因此允许通过部分请求试着看看能不能处理成功,如果这些请求处理成功,那么就认为之前导致失败的错误已经被修复,此事熔断器就切换到闭合状态,并且将计数器重置。如果这些试着发送的请求还是失败,则认为之前的问题没有解决,熔断器切回到打开模式,然后开始重置计数器给系统一定的时间来修复错误
  • 接着重复以上过程,直到半打开状态重复的次数达到一定的阈值发现错误还没被修复,从而触发”降级”状态

优缺点:

优点

  • 防止故障扩散,保护系统稳定性。
  • 减少资源浪费,避免大量失败请求。

缺点

  • 一旦熔断器打开,需要一定时间来恢复,可能会影响到正常请求的处理速度。

降级

场景

某些时候系统会遇到负载过高的问题,当系统外来的或者内部的负载过高,超过预先定义的阈值,为了保证更加重要的业务的服务质量,希望将一些非核心的业务降低服务质量,从而释放一些额外的资源给紧急业务使用。
比如一个分布式系统里的读、写、数据校验、空间回收都比较消耗资源,在业务高峰期为了保证读和写的服务治理,可以把数据校验的服务通过限流或者减少线程数之类的方式,使得该服务能够调用的资源配额减少,从而释放部分资源给读和写使用,保证读写的服务质量

定义

当系统遇到高负载或者部分服务不可用时,通过牺牲部分功能或服务的质量来保障核心功能的可用性。

在读和写业务不繁忙的时候,降低业务的资源配额,从而释放资源给空间回收使用。通过这种方式动态调整局部业务的服务质量从而保证关键业务的服务治理,提升用户体验

触发策略

  • 超时降级:在超时重试的次数达到一个阈值后就触发降级
  • 失败比率重试:当某个服务的失败比率达到一定比率后开始降级
  • 系统故障降级:比如网络故障,硬盘故障,电源故障,服务器故障,数据中心故障等等
  • 限流降级:某些访问量太大的场景会触发限流,当达到限流的阈值后,请求也会被降级
  • 重要业务救急:比如为了保证读或者查询的功能,降低写、数据校验的资源配额

优缺点:

优点

  • 保证核心功能的可用性,提高系统的稳定性。
  • 可以根据实际情况进行灵活配置,适应不同的业务场景。

缺点

  • 降低了系统的完整性和功能性,可能会影响用户体验。

限流

原理

通过设定每个服务或接口的最大请求速率,超过该速率的请求会被丢弃或者延迟处理。

优缺点:

优点

  • 保护系统免受过载,提高系统的稳定性和可用性。
  • 防止恶意攻击或者异常情况下的资源耗尽。

缺点

  • 可能会影响部分合法请求的处理速度,需要权衡限流策略的精确度和系统性能。

限流算法有哪些

漏桶算法

漏桶大小固定,处理速度固定,但请求进入速度不固定(在突发情况请求过多时,会丢弃过多的请求)。

步骤

水(请求)先进入到漏桶里,漏桶以一定的速度出水,当水流入速度过大会超过桶可接纳的容量时直接溢出。

漏桶算法其实很简单,可以粗略的认为就是注水漏水过程,往桶中以任意速率流入水,以一定速率流出水,当水超过桶容量(capacity)则丢弃,因为桶容量是不变的,保证了整体的速率。

令牌桶算法

令牌桶的大小固定,令牌的产生速度固定,但是消耗令牌(即请求)速度不固定(可以应对一些某些时间请求过多的情况);每个请求都会从令牌桶中取出令牌,如果没有令牌则丢弃该次请求。

计数器

在一段时间间隔内(时间窗/时间区间),处理请求的最大数量固定,超过部分不做处理。

步骤

  • 在一开 始的时候,我们可以设置一个计数器counter,每当一个请求过来的时候,counter就加1,如果counter的值大于100并且该请求与第一个请求的间隔时间还在1分钟之内,那么说明请求数过多,拒绝访问;

  • 如果该请求与第一个请求的间隔时间大于1分钟,且counter的值还在限流范围内,那么就重置 counter,就是这么简单粗暴。

存在的问题

这个算法虽然简单,但是有一个十分致命的问题,那就是临界问题,我们看下图:

从上图中我们可以看到,假设有一个恶意用户,他在0:59时,瞬间发送了100个请求,并且1:00又瞬间发送了100个请求,那么其实这个用户在 1秒里面,瞬间发送了200个请求。

我们刚才规定的是1分钟最多100个请求(规划的吞吐量),也就是每秒钟最多1.7个请求,用户通过在时间窗口的重置节点处突发请求, 可以瞬间超过我们的速率限制。

用户有可能通过算法的这个漏洞,瞬间压垮我们的应用。

漏桶和令牌桶算法的区别

漏桶

把请求比作是水,水来了都先放进桶里,并以限定的速度出水,当水来得过猛而出水不够快时就会导致水直接溢出,即拒绝服务。它能够强行控制出口速率的匀速。没法应变突发大规模请求。如果突然来了大量请求,即使桶内容量足够,也只能以一个固定的速率放过。

令牌桶

令牌桶算法能够在限制数据的平均传输速率的同时还允许某种程度的突发传输。即如果突然来了大量请求,只要令牌够用,就可以一次性放过。

令牌桶算法适合绝大部分场景,因为任何网络或者服务,接收到的请求不可能是永远固定不变的,总有时候突然会有大量请求,而且系统一般也能处理(系统处理能力用令牌数量控制),所有令牌桶在限流方案中用的比较多。

参考

[1]分布式系统常见设计

br>


文章作者: Alex
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Alex !
  目录