【分布式】10张图带你彻底搞懂限流、熔断、服务降级

news2024/9/24 9:20:56

文章目录

  • 1 限流
    • 1.1 限流指标
      • 1.1.1 TPS
      • 1.1.2 HPS
      • 1.1.3 QPS
    • 1.2 限流方法
      • 1.2.1 流量计数器
      • 1.2.2 滑动时间窗口
      • 1.2.3 漏桶算法
      • 1.2.4 令牌桶算法
      • 1.2.5 分布式限流
      • 1.2.6 hystrix限流
        • 1.2.6.1 信号量限流
        • 1.2.6.2 线程池限流
  • 2 熔断
    • 2.1 断路器的状态
    • 2.2 需要考虑的问题
    • 2.3 使用场景
  • 3 服务降级
    • 3.1 使用场景
    • 3.2 使用hystrix降级
      • 3.2.1 异常降级
      • 3.2.2 调用超时降级
  • 总结

在分布式系统中,如果某个服务节点发生故障或者网络发生异常,都有可能导致调用方被阻塞等待,如果超时时间设置很长,调用方资源很可能被耗尽。这又导致了调用方的上游系统发生资源耗尽的情况,最终导致系统雪崩。

如下图:
在这里插入图片描述

如果D服务发生了故障不能响应,B服务调用D时只能阻塞等待。假如B服务调用D服务设置超时时间是10秒,请求速率是每秒100个,那10秒内就会有1000个请求线程被阻塞等待,如果B的线程池大小设置1000,那B系统因为线程资源耗尽已经不能对外提供服务了。而这又影响了入口系统A的服务,最终导致系统全面崩溃。

提高系统的整体容错能力是防止系统雪崩的有效手段。

在Martin Fowler和James Lewis的文章 《Microservices: a definition of this new architectural term》[1]中,提出了微服务的9个特征,其中一个是容错设计。

要防止系统发生雪崩,就必须要有容错设计。如果遇到突增流量,一般的做法是对非核心业务功能采用熔断和服务降级的措施来保护核心业务功能正常服务,而对于核心功能服务,则需要采用限流的措施。

今天我们来聊一聊系统容错中的限流、熔断和服务降级。

1 限流

当系统的处理能力不能应对外部请求的突增流量时,为了不让系统奔溃,必须采取限流的措施。

1.1 限流指标

1.1.1 TPS

系统吞吐量是衡量系统性能的关键指标,按照事务的完成数量来限流是最合理的。

但是对实操性来说,按照事务来限流并不现实。在分布式系统中完成一笔事务需要多个系统的配合。比如我们在电商系统购物,需要订单、库存、账户、支付等多个服务配合完成,有的服务需要异步返回,这样完成一笔事务花费的时间可能会很长。如果按照TPS来进行限流,时间粒度可能会很大大,很难准确评估系统的响应性能。

1.1.2 HPS

每秒请求数,指每秒钟服务端收到客户端的请求数量。

❝如果一个请求完成一笔事务,那TPS和HPS是等同的。但在分布式场景下,完成一笔事务可能需要多次请求,所以TPS和HPS指标不能等同看待。

1.1.3 QPS

服务端每秒能够响应的客户端查询请求数量。

❝如果后台只有一台服务器,那HPS和QPS是等同的。但是在分布式场景下,每个请求需要多个服务器配合完成响应。 ❞

❝目前主流的限流方法多采用HPS作为限流指标。 ❞

1.2 限流方法

1.2.1 流量计数器

这是最简单直接的方法,比如限制每秒请求数量100,超过100的请求就拒绝掉。

但是这个方法存在2个明显的问题:

单位时间(比如1s)很难把控,如下图:
在这里插入图片描述

这张图上,从下面时间看,HPS没有超过100,但是从上面看HPS超过100了。

有一段时间流量超了,也不一定真的需要限流,如下图,系统HPS限制50,虽然前3s流量超了,但是如果读超时时间设置为5s,并不需要限流。
在这里插入图片描述

1.2.2 滑动时间窗口

滑动时间窗口算法是目前比较流行的限流算法,主要思想是把时间看做是一个向前滚动的窗口,如下图:

在这里插入图片描述

开始的时候,我们把t1t5看做一个时间窗口,每个窗口1s,如果我们定的限流目标是每秒50个请求,那t1t5这个窗口的请求总和不能超过250个。

这个窗口是滑动的,下一秒的窗口成了t2~t6,这时把t1时间片的统计抛弃,加入t6时间片进行统计。这段时间内的请求数量也不能超过250个。

滑动时间窗口的优点是解决了流量计数器算法的缺陷,但是也有2个问题:

  • 流量超过就必须抛弃或者走降级逻辑
  • 对流量控制不够精细,不能限制集中在短时间内的流量,也不能削峰填谷

1.2.3 漏桶算法

漏桶算法的思想如下图:
在这里插入图片描述

在客户端的请求发送到服务器之前,先用漏桶缓存起来,这个漏桶可以是一个长度固定的队列,这个队列中的请求均匀的发送到服务端。

如果客户端的请求速率太快,漏桶的队列满了,就会被拒绝掉,或者走降级处理逻辑。这样服务端就不会受到突发流量的冲击。

漏桶算法的优点是实现简单,可以使用消息队列来削峰填谷。

但是也有3个问题需要考虑:

  • 漏桶的大小,如果太大,可能给服务端带来较大处理压力,太小可能会有大量请求被丢弃。
  • 漏桶给服务端的请求发送速率。
  • 使用缓存请求的方式,会使请求响应时间变长。

❝漏桶大小和发送速率这2个值在项目上线初期都会根据测试结果选择一个值,但是随着架构的改进和集群的伸缩,这2个值也会随之发生改变。 ❞

1.2.4 令牌桶算法

令牌桶算法就跟病人去医院看病一样,找医生之前需要先挂号,而医院每天放的号是有限的。当天的号用完了,第二天又会放一批号。

算法的基本思想就是周期性的执行下面的流程:
在这里插入图片描述

客户端在发送请求时,都需要先从令牌桶中获取令牌,如果取到了,就可以把请求发送给服务端,取不到令牌,就只能被拒绝或者走服务降级的逻辑。如下图:
在这里插入图片描述

❝令牌桶算法解决了漏桶算法的问题,而且实现并不复杂,使用信号量就可以实现。在实际限流场景中使用最多,比如google的guava中就实现了令牌桶算法限流,感兴趣可以研究一下。

1.2.5 分布式限流

如果在分布式系统场景下,上面介绍的4种限流算法是否还适用呢?

以令牌桶算法为例,假如在电商系统中客户下了一笔订单,如下图:
在这里插入图片描述

如果我们把令牌桶单独保存在一个地方(比如redis中)供整个分布式系统用,那客户端在调用组合服务,组合服务调用订单、库存和账户服务都需要跟令牌桶交互,交互次数明显增加了很多。

有一种改进就是客户端调用组合服务之前首先获取四个令牌,调用组合服务时减去一个令牌并且传递给组合服务三个令牌,组合服务调用下面三个服务时依次消耗一个令牌。

1.2.6 hystrix限流

hystrix可以使用信号量和线程池来进行限流。

1.2.6.1 信号量限流

hystrix可以使用信号量进行限流,比如在提供服务的方法上加下面的注解。这样只能有20个并发线程来访问这个方法,超过的就被转到了errMethod这个降级方法。

@HystrixCommand(
 commandProperties= {
   @HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE"),
   @HystrixProperty(name="execution.isolation.semaphore.maxConcurrentRequests", value="20")
 },
 fallbackMethod = "errMethod"
)

1.2.6.2 线程池限流

hystrix也可以使用线程池进行限流,在提供服务的方法上加下面的注解,当线程数量

@HystrixCommand(
    commandProperties = {
            @HystrixProperty(name = "execution.isolation.strategy", value = "THREAD")
    },
    threadPoolKey = "createOrderThreadPool",
    threadPoolProperties = {
            @HystrixProperty(name = "coreSize", value = "20"),
   @HystrixProperty(name = "maxQueueSize", value = "100"),
            @HystrixProperty(name = "maximumSize", value = "30"),
            @HystrixProperty(name = "queueSizeRejectionThreshold", value = "120")
    },
    fallbackMethod = "errMethod"
)

❝这里要注意:在java的线程池中,如果线程数量超过coreSize,创建线程请求会优先进入队列,如果队列满了,就会继续创建线程直到线程数量达到maximumSize,之后走拒绝策略。但在hystrix配置的线程池中多了一个参数queueSizeRejectionThreshold,如果queueSizeRejectionThreshold
<
maxQueueSize,队列数量达到queueSizeRejectionThreshold就会走拒绝策略了,因此maximumSize失效了。如果queueSizeRejectionThreshold

maxQueueSize,队列数量达到maxQueueSize时,maximumSize是有效的,系统会继续创建线程直到数量达到maximumSize。Hytrix线程池设置坑[2]

2 熔断

相信大家对断路器并不陌生,它就相当于一个开关,打开后可以阻止流量通过。比如保险丝,当电流过大时,就会熔断,从而避免元器件损坏。

服务熔断是指调用方访问服务时通过断路器做代理进行访问,断路器会持续观察服务返回的成功、失败的状态,当失败超过设置的阈值时断路器打开,请求就不能真正地访问到服务了。

为了更好地理解,我画了下面的时序图:

在这里插入图片描述

❝可以参考Martin Fowler的论文《CircuitBreaker》[3]。 ❞

2.1 断路器的状态

断路器有3种状态:

  • CLOSED:默认状态。断路器观察到请求失败比例没有达到阈值,断路器认为被代理服务状态良好。
  • OPEN:断路器观察到请求失败比例已经达到阈值,断路器认为被代理服务故障,打开开关,请求不再到达被代理的服务,而是快速失败。
  • HALF OPEN:断路器打开后,为了能自动恢复对被代理服务的访问,会切换到半开放状态,去尝试请求被代理服务以查看服务是否已经故障恢复。如果成功,会转成CLOSED状态,否则转到OPEN状态。
    断路器的状态切换图如下:
    在这里插入图片描述

2.2 需要考虑的问题

使用断路器需要考虑一些问题:

  • 针对不同的异常,定义不同的熔断后处理逻辑。
  • 设置熔断的时长,超过这个时长后切换到HALF OPEN进行重试。
  • 记录请求失败日志,供监控使用。
  • 主动重试,比如对于connection timeout造成的熔断,可以用异步线程进行网络检测,比如telenet,检测到网络畅通时切换到HALF OPEN进行重试。
  • 补偿接口,断路器可以提供补偿接口让运维人员手工关闭。
  • 重试时,可以使用之前失败的请求进行重试,但一定要注意业务上是否允许这样做。

2.3 使用场景

  • 服务故障或者升级时,让客户端快速失败
  • 失败处理逻辑容易定义
  • 响应耗时较长,客户端设置的read timeout会比较长,防止客户端大量重试请求导致的连接、线程资源不能释放

3 服务降级

前面讲了限流和熔断,相比来说,服务降级是站在系统全局的视角来考虑的。

在服务发生熔断后,一般会让请求走事先配置的处理方法,这个处理方法就是一个降级逻辑。

服务降级是对非核心、非关键的服务进行降级。

3.1 使用场景

  • 服务处理异常,把异常信息直接反馈给客户端,不再走其他逻辑
  • 服务处理异常,把请求缓存下来,给客户端返回一个中间态,事后再重试缓存的请求
  • 监控系统检测到突增流量,为了避免非核心业务功能耗费系统资源,关闭这些非核心功能
  • 数据库请求压力大,可以考虑返回缓存中的数据
  • 对于耗时的写操作,可以改为异步写
  • 暂时关闭跑批任务,以节省系统资源

3.2 使用hystrix降级

3.2.1 异常降级

hystrix降级时可以忽略某个异常,在方法上加上@HystrixCommand注解:

下面的代码定义降级方法是errMethod,对ParamErrorException和BusinessTypeException这两个异常不做降级处理。

@HystrixCommand(
 fallbackMethod = "errMethod",
 ignoreExceptions = {ParamErrorException.class, BusinessTypeException.class}
)

3.2.2 调用超时降级

专门针对调用第三方接口超时降级。

下面的方法是调用第三方接口3秒未收到响应就降级到errMethod方法。

@HystrixCommand(
    commandProperties = {
            @HystrixProperty(name="execution.timeout.enabled", value="true"),
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="3000"),
    },
    fallbackMethod = "errMethod"
)

总结

限流、熔断和服务降级是系统容错的重要设计模式,从一定意义上讲限流和熔断也是一种服务降级的手段。

熔断和服务降级主要是针对非核心业务功能,而核心业务如果流程超过预估的峰值,就需要进行限流。

对于限流,选择合理的限流算法很重要,令牌桶算法优势很明显,也是使用最多的限流算法。

在系统设计的时候,这些模式需要配合业务量的预估、性能测试的数据进行相应阈值的配置,而这些阈值最好保存在配置中心,方便实时修改。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/382825.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

游戏开发是个“坑”,而且是个“天坑”

本文首发于CSDN公众号 作者 | 开发游戏的老王 责编 | 梦依丹 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 各位游戏开发者大家好&#xff0c;我是开发游戏的老王&#xff0c;一名游戏开发者同时也是一名高校游戏方向的主讲教师&#xff0c;从事游戏开发及相关教…

HTTP缓存从入门到踹门

1 与缓存相关的字段Expires&#xff1a;缓存的绝对过期时间Cache-Control&#xff1a;缓存的相对过期时间Last-Modified&#xff1a;缓存上一次修改的时间&#xff08;服务端保存&#xff09;If-Modified-Since&#xff1a;缓存上一次修改的时间&#xff08;客户端保存&#xf…

第十一届蓝桥杯省赛——2解密

题目&#xff1a;【问题描述】小明设计了一种文章加密的方法&#xff1a;对于每个字母 c&#xff0c;将它变成某个另外的字符 Tc。下表给出了字符变换的规则&#xff1a;字母cTc字母cTc字母cTc字母cTcaynlAYNLbxogBXOGcmpoCMPOddquDDQUearfEARFfcssFCSSgitzGITZhkupHKUPinvwINV…

【ArcGIS Pro二次开发】(11):面要素的一键拓扑

在工作中&#xff0c;经常需要对要素进行拓扑检查。 在ArcGIS Pro中正常的工作流程是在数据库中【新建要素数据集——新建拓扑——将要素加入拓扑——添加规则——验证】&#xff0c;工作流程不算短&#xff0c;操作起来比较繁琐。 下面以一个例子演示如何在ArcGIS Pro SDK二次…

数组一次性删除多条数据

需求描述 最后提交时删除表格中的空行 实现方法 单行删除 - 并不是一次性删除 表格每行的最后设置删除按钮&#xff0c;点击时将当前行的索引传递给方法&#xff0c;splice 删除当前行。 <el-table :data"tableData" class"myTable" border>..…

爬虫实战进阶版【1】——某眼专业版实时票房接口破解

某眼专业版-实时票房接口破解 某眼票房接口:https://piaofang.maoyan.com/dashboard-ajax 前言 当我们想根据某眼的接口获取票房信息的时候,发现它的接口处的参数是加密的,如下图: 红色框框的参数都是动态变化的,且signKey明显是加密的一个参数。对于这种加密的参数,我们需要…

第14届蓝桥杯STEMA测评真题剖析-2023年2月12日Scratch编程初中级组

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第103讲。 蓝桥杯选拔赛现已更名为STEMA&#xff0c;即STEM 能力测试&#xff0c;是蓝桥杯大赛组委会与美国普林斯顿多…

域权限维持之创建DSRM后门

DSRM&#xff08;目录服务还原模式&#xff09;&#xff0c;在初期安装域控的时候会让我们设置DSRM的管理员密码&#xff0c;这个密码是为了在后期域控发生问题时修复、还原或重建活动目录。DSRM账户实际上是administrator账户&#xff0c;并且该账户的密码在创建之后很少使用。…

Azure OpenAI 官方指南 01|GPT-3 的原理揭秘与微调技巧

Azure OpenAI 服务在微软全球 Azure 平台正式发布后&#xff0c;迅速成为众多用户最关心的服务之一。 Azure OpenAI 服务允许用户通过 REST API 访问 OpenAI 的强大语言模型&#xff0c;包括 GPT-3、Codex 和 Embeddings 模型系列。本期&#xff0c;我们将为您揭秘 Azure Open…

乌班图安装kvm并配置网络

乌班图22安装KVM 1.安装KVM sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virt-manager virtinstsudo adduser id -un libvirt sudo adduser id -un kvm sudo apt install virtinst qemu-efi sudo systemctl enable --now libvirtd sudo s…

Tcl_Init error: Can‘t find a usable init.tcl in the following directories

目录 问题 解决 小结 问题 最近在研究开源波形显示软件gtkwave时,Ubuntu18.04下编译打包完成,移植到另一个电脑上运行时,出现以下错误,如图: 擦掉的部分是一些路径信息,这个错误提示意味着您的系统中缺少所需的 Tcl 初始化文件,路径下确实没有init.tcl文…

嵌入式 LVGL移植到STM32F4

目录 LVGL简介 1、特点 2、LVGL的硬件要求 3、相关网站 4、LVGL源码下载 5、LVGL移植要求 5.1 移植过程-添加源码 2、更改接口文件 3、显示实现 4、添加外部中文字体的方法 5、编译下载后有几种情况 6、调用显示 6、GUI-Guider使用 6.1 安装软件 6.2 使用…

Kakfa详解(一)

kafka使用场景 canal同步mysqlelk日志系统业务系统Topic kafka基础概念 Producer: 消息生产者&#xff0c;向kafka发送消息Consumer: 从kafka中拉取消息消费的客户端Consumer Group: 消费者组&#xff0c;消费者组是多个消费者的集合。消费者组之间互不影响&#xff0c;所有…

Wireshark+Go捕获本地TCP通信

初学计网&#xff0c;使用Wireshark观察本地端口间TCP通信过程。 目录 步骤1&#xff1a; 步骤2&#xff1a; 步骤3&#xff1a; 步骤1&#xff1a; 使用go语言搭建本地客户端与服务器TCP通信&#xff0c;测试完成后在步骤2先运行服务器&#xff0c;再运行客户端。 服务器…

C语言查漏补缺(进阶)volatile、__attribute__、void*、地址对齐、$$Super$main

最近在学习RT-Thread&#xff0c;在看其源码的时候发现了许多自己不太了解的C语言知识点&#xff0c;在此查漏补缺一下。 1. 关键字 volatile volatile是C90新增关键字&#xff0c;volatile的的中文意思是adj.易变的&#xff1b;无定性的&#xff1b;无常性的&#xff1b;可…

如何使用FarsightAD在活动目录域中检测攻击者部署的持久化机制

关于FarsightAD FarsightAD是一款功能强大的PowerShell脚本&#xff0c;该工具可以帮助广大研究人员在活动目录域遭受到渗透攻击之后&#xff0c;检测到由攻击者部署的持久化机制。 该脚本能够生成并导出各种对象及其属性的CSV/JSON文件&#xff0c;并附带从元数据副本中获取…

Python|每日一练|递归|数学|数组|动态规划|树|深度优先搜索|单选记录:排列序列|三角形最小路径和|求根节点到叶节点数字之和

1、排列序列&#xff08;递归&#xff0c;数学&#xff09; 给出集合 [1,2,3,...,n]&#xff0c;其所有元素共有 n! 种排列。 按大小顺序列出所有排列情况&#xff0c;并一一标记&#xff0c;当 n 3 时, 所有排列如下&#xff1a; "123""132""213…

webpack基本使用和开发环境配置

目录 1 webpack 基本使用 01 webpack 简介 02 webpack 初体验 2 webpack开发环境配置 03 打包样式资源 04 打包html资源 05 打包图片资源 06 打包其他资源&#xff08;以打包icon为例&#xff09; 07 devServer 08.开发环境配置 1 webpack 基本使用 由于笔记文档没有…

批量下载Landsat遥感影像的方法

本文介绍在USGS网站批量下载Landsat系列遥感影像的方法。首先打开EarthExplorer的官网&#xff0c;首先完成注册与登录。接下来点击左侧“Search Criteria”&#xff0c;首先选择研究区域。研究区域的划定有多种方法&#xff0c;可以依据地理名称选定研究区域&#xff0c;也可以…

klipper使用webcam设置多个摄像头方式

一、前言 使用klipper设置多个摄像头&#xff0c;折腾了好些天&#xff0c;网上资料很少&#xff0c;这里写一个帖子记录一下 二、环境 参考链接&#xff1a;https://www.cnblogs.com/sjqlwy/p/klipper_webcam.html 我的klipper安装在香橙派上面&#xff0c;系统是debian&a…