微服务 - 如何进行服务限流和熔断

Posted Java资料站

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了微服务 - 如何进行服务限流和熔断相关的知识,希望对你有一定的参考价值。

优质文章,第一时间送达

  作者 |  王泽宾

来源 |  urlify.cn/UN3Mju

一、服务雪崩

微服务架构是将单个应用程序被划分成各种小而连接的服务,每一个服务完成一个单一的业务功能。相对于传统的单体服务,微服务具有隔离性、技术异构性、可扩展性以及简化部署等优点。通常一个应用由多个微服务组成,微服务之间的数据交互需要通过远过程调用的方式完成。

下图是一个微服务之间互相调用的场景:

微服务A调用微服务B、C和D,微服务C又调用微服务E。假设某一时刻,微服务E变为不可用。微服务C需要等待微服务E返回结果,于是请求就会逐渐堆积在微服务C,形成阻塞。随着微服务C堆积的请求不断增加,微服务A也会随之慢慢阻塞。因为服务器所能支撑的并发数有限,所以最终会耗尽服务器资源,从而导致调用链条上更多的微服务不可用,形成雪崩效应。这种由一个服务崩溃导致整条服务链崩溃的情况,我们就称之为服务雪崩。

在微服务架构中,通常有两种情况会导致服务雪崩:

  1. 突发性的访问量剧增,超出了服务处理极限

  2. 调用链条上某个服务出现故障或者响应慢(延迟)

    针对以上这两种情况,产生了对应的解决方案:服务限流和服务熔断。

二、 服务限流

服务限流是指在一定时间段内限制服务的请求量以保护系统,主要用于防止突发流量而导致的服务崩溃,比如秒杀、抢购、双十一等场景,也可以用于安全目的,比如应对外部暴力攻击。

常用的限流算法有以下几种:

  • 计数器算法

    通过维护一个内部计数器,对一段时间的服务请求进行累计,判断计数器是否达到预先设定的阈值。如果没有达到阈值,就允许请求通过,并且计数器加1;如果达到阈值,则拒绝服务,抛弃请求。进入下一个计时周期后,计数器清零,重新计数。

    计数器算法是限流算法中最简单的算法,缺点是有突刺现象,不仅请求通过的速率不均匀,而且请求输出的速率也不均匀,对后续处理的并发要求比较高。比如:设定服务周期为1秒,请求的上限阈值为1000。如果前1ms内已经收到1000个请求,那么剩下的时间都只能拒绝,而且后端服务需要并发处理1000个请求。

  • 漏桶算法

    漏桶算法的原理可以这样理解,将服务请求想象成流入漏桶的水,漏桶中的水以恒定的速率从桶底流出,当流入漏桶的水速度过快,超过了漏桶容量时,则直接溢出。所以,漏桶算法能够控制服务请求按照固定速率均匀输出,平滑突发流量,实现流量整形,为后续处理提供一个稳定的流量。但是,漏桶算法无法控制请求按照一定的速率均匀输入。

  • 令牌桶算法

    令牌桶算法是速率限制(Rate Limiting)和流量整形(Traffic Shaping)中最常使用的一种算法。典型情况下,令牌桶算法用来控制发送到网络上的数据的数目,并允许突发数据的发送。

    首先设定一个可以存放固定数量的令牌桶,使用某种机制以恒定的速度产生令牌。每次请求调用时,都必须去桶中获取令牌,只有拿到令牌,才能放行,否则只能等待可用的令牌,或者直接拒绝。如果桶中的令牌消耗的速度小于产生的速度,令牌就会不断地增多,直至填满,再产生的令牌就会从桶中溢出。

    所以,令牌桶算法既可以控制请求均匀输入的速度,又可以控制请求的均匀输出速率。

三、服务熔断

我们在各种场景下都会接触到熔断这两个字。高压电路中,如果某处电压过高,熔断器就会熔断,对电路进行保护。股票交易中,如果股票涨跌幅过大,也会采用熔断机制,暂停交易,来控制交易风险。

同样,在微服务架构中,熔断机制也是起着类似的作用。当调用链路中的某个微服务长时间不可用或者有延迟,响应过慢,系统就会熔断对该节点微服务的调用,快速返回错误信息。当监控到该微服务正常工作后,再次恢复该调用链路。

四、Hystrix

服务熔断和服务限流作为微服务架构中作为服务治理的重要手段,在很多开源框架或者产品中都包含了此类功能。比如阿里dubbo,Netflix Hystrix,go-micro,go-kit等。

Hystrix是Netflix公司的开源项目,它是一个延迟和故障容错库,旨在隔离对远程系统、服务和第三方库的访问点,防止级联故障,并在无法避免发生故障的复杂分布式系统中实现了弹性。

Hystrix可以做到以下事情:

  • 通过控制延迟和故障来保障第三方服务调用的可靠性

  • 在复杂的分布式系统中防止级联故障,防止雪崩

  • 快速失败、快速恢复

  • 回退并优雅降级

  • 提供近实时监控、报警和操作控制

Hystrix 能使你的系统在出现依赖服务失效的时候,通过隔离系统所依赖的服务,防止服务级联失败,同时提供失败回退机制,更优雅地应对失效,并使你的系统能更快地从异常中恢复。

使用Hystrix 非常简单:

package main

import (
 "github.com/afex/hystrix-go/hystrix"
 "log"
)

func main() {
 // 每一类微服务、远程系统、第三方库的调用都被包装为一个命令,
 // 调用之前需要先行设置相关的配置信息
 hystrix.ConfigureCommand(
  "ServiceA", // 命令名称
  hystrix.CommandConfig{
   Timeout:                1000, // 超时时间设置(毫秒)
   MaxConcurrentRequests:  1,    // 最大并发请求数
   ErrorPercentThreshold:  50,   // 错误率阈值,超过阈值将熔断服务
   SleepWindow:            5000, // 服务熔断后,过多长时间,熔断器再次检测是否开启(毫秒)
   RequestVolumeThreshold: 20,   // 服务熔断前,所需的最小请求量,请求阈值  熔断器是否打开首先要满足这个条件;这里的设置表示至少有5个请求才进行ErrorPercentThreshold错误百分比计算
  })

 // 使用hystrix调用远程服务,并根据命令名称启用ConfigureCommand中设置的参数
 _ = hystrix.Do(
  "ServiceA", // 命令名称
  // 运行函数
  func() error {
   // 调用远程服务
   log.Println("invoke a remote service")
   return nil
  },
  // 失败回退函数
  func(err error) error {
   log.Println("fall back")
   return err
  },
 )
}

注:
本文全部源代码位于:https://github.com/wangshizebin/micro-service






粉丝福利:实战springboot+CAS单点登录系统视频教程免费领取

以上是关于微服务 - 如何进行服务限流和熔断的主要内容,如果未能解决你的问题,请参考以下文章

微服务高可用之熔断器实现原理与 Golang 实践

soul 网关(十五):限流和熔断的扫盲篇

Sentinel 流量防卫兵-SpringCloudAlibaba No.4

阿里中间件Sentinel 关于限流和降级

微服务架构中的熔断器设计与实现( Golang 版)

高并发整体可用性:一文详解降级限流和熔断