分布式高可用 | 限流、熔断、降级

在分布式系统中,限流、熔断和降级,这三者都是流量超过时,通过一定的方式去保护系统。而高可用的意思是在系统出现故障或异常情况时仍然能够保持稳定的运行状态。 通常我们的分布式系统如下图所示。 Service A 是主调,Service B 是被调。他们各自分别都有两个实例,即两个副本,为实现分布式高可用。 限流:一般是在被调生效,即图中的绿色框框所处的位置 熔断:一般是在主调生效,也有部分熔断设计在被调生效,如图中红色块所处的位置。 降级:一般从用户侧观察,是否享有的服务变差了。限流和熔断都会带来降级。 限流 - Rate Limiting 限流是从系统的流量入口考虑,从进入的流量上进行限制,达到保护系统的作用。是指需要限制并发/请求量的场景(如秒杀等),通过限流保护服务免受雪崩之灾。 主流的限流限流算法有计数器、令牌桶、漏桶。 🔺 计数器 多少次每秒/每分/每天,根据作用范围的不同,计数器两类 单机计数器即 Local Counter(每个机器都有自己的计数器) 全局计数器也就是分布式计数器即 Global Counter(所有机器公有一个计数器阈值) 🔺 令牌桶 令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。 令牌桶算法是网络流量整形(Traffic Shaping)和速率限制(Rate Limiting)中最常使用的算法。 通常,令牌桶算法用来控制发送到网络上的数据的数目,并允许突发数据的发送。 🔺 漏桶 漏桶算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水,当水流入速度过大会直接溢出,可以看出漏桶算法能强行限制数据的传输速率。 限流与压测 通常限流需要配合压测来做,不然也不知道系统的负载极限在哪里。初期做法是通过对单一服务的压测,或全链路压测得到一个阈值(静态)。 该处做法就是简单,缺点是随着业务复杂度的上升,静态阈值将会不能代表服务的真实服务能力,所以一般在活动或者大促前,去组织一批服务压测。更好的做法是全链路压测日常化,然后随时调整这个阈值。实现阈值从静态到动态的转变。 熔断 - Circuit Breaker Mechanism 如图所示,熔断器首先是关闭的,当主调失败到达了一定阈值后,此时熔断器打开(主调的请求不会再到被调了,压根就不会发出请求),过了一个"冷却时间"后,熔断器此时会处于一个半开的状态,会有请求到被调。 如果请求成功就关闭熔断器(后端服务恢复),否则就继续打开熔断器。熔断强调的是服务之间的调用能实现自我恢复的状态。 例如你的 A 服务里面的一个功能依赖 B 服务,这时候 B 服务出问题了,返回的很慢。这种情况可能会因为这么一个功能而拖慢了 A 服务里面的所有功能,因此我们这时候就需要熔断! 即当发现 A 要调用这 B 时就直接返回错误(或者返回其他默认值),就不去请求B了。 🔺 主调熔断 主调熔断是熔断的主要场景,在微服务中,通过结合服务注册和发现组件来进行使用的。主调通过服务发现组件来获取被调的实例,如果主调的失败达到了一个阈值,服务发现组件会熔断被调的实例,也就是不再会去请求被调。 🔺 被调熔断 被调熔断,被调实例获取当前的实例负载情况,如果 cpu/内存/io 等超过了一定的阈值,那么就会触发熔断,将抛弃进来的请求。此时熔断和限流比较像,一个是基于负载情况,一个是根据配置的阈值情况。 降级 降级也就是服务降级,当我们的服务器压力剧增为了保证核心功能的可用性 ,而选择性的降低一些功能的可用性,或者直接关闭该功能。这就是典型的丢车保帅了。当服务暂时不可用或者影响到核心流程时,需要待高峰或者问题解决后再打开。...

May 20, 2023