限流、熔断、服务降级

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

举例:如果 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 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 滑动时间窗口

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

开始的时候,我们把 t1~t5 看做一个时间窗口,每个窗口 1s,如果我们定的限流目标是每秒 50 个请求,那 t1~t5 这个窗口的请求总和不能超过 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]

熔断

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

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

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

可以参考 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.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"

)

总结

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

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

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[Vulfocus解题系列]Spring WebFlow 远程代码执行漏洞(CVE-2017-4971)

简介 Spring WebFlow 是一个适用于开发基于流程的应用程序的框架&#xff08;如购物逻辑&#xff09;&#xff0c;可以将流程的定义和实现流程行为的类和视图分离开来。在其 2.4.x 版本中&#xff0c;如果我们控制了数据绑定时的field&#xff0c;将导致一个SpEL表达式注入漏洞…

科大奥瑞物理实验——声速的测量

实验名称&#xff1a;声速的测量 1. 实验目的&#xff1a; &#xff08;1&#xff09;了解超声波的发射和接收方法。 &#xff08;2&#xff09;加深对振动合成、波动干涉等理论知识的理解。 &#xff08;3&#xff09;掌握用驻波法和相位法测声速。 2. 实验器材&#xff1a…

如何挖掘用户需求的真正动机?关键是4大因素

需求分析实质是挖掘用户内心真正的目标&#xff0c;并转化为产品需求的过程。而用户需求是用户基于自身角度提出的表层需求&#xff0c;这些需求往往有用户期望的产品功能指向。而在产品功能指向的背后&#xff0c;暗藏着潜在的用户动机&#xff0c;这是用户真正希望解决的核心…

【尚硅谷】Java数据结构与算法笔记13 - 图

文章目录一、图的基本介绍1.1 为什么要有图1.2 图的举例说明1.3 图的常用概念二、图的表示方式2.1 邻接矩阵2.2 邻接表三、图的快速入门案例四、图的遍历4.1 深度优先遍历 DFS4.1.1 基本思想4.1.2 算法步骤4.1.3 图示4.2 广度优先遍历 BFS4.2.1 基本思想4.2.2 算法步骤4.2.3 图…

【机器学习】P8 过拟合与欠拟合、正则化与正则化后的损失函数和梯度下降

过拟合与欠拟合、正则化与正则化后的损失函数和梯度下降过拟合与欠拟合过拟合与欠拟合直观理解线性回归中 过拟合与欠拟合逻辑回归中 过拟合与欠拟合过拟合与欠拟合的解决办法过拟合解决方案欠拟合解决方案包含正则化的损失函数正则化线性回归损失函数正则化逻辑回归损失函数包…

java爬虫利器Jsoup的使用

对于长期使用java做编程的程序猿应该知道&#xff0c;java支持的爬虫框架还是有很多的&#xff0c;如&#xff1a;ebMagic、Spider、Jsoup等。今天我们就用Jsoup来实现一个小小的爬虫程序&#xff0c;Jsoup作为kava的HTML解析器&#xff0c;可以直接对某个URL地址、HTML文本内容…

焦虑真的好吗 过度的焦虑存在哪些影响

日常常见的焦虑情绪真的好吗&#xff1f;焦虑是我们七情中的一种正常情绪表现&#xff0c;我们生活当中很多因素都可能会导致我们产生焦虑的情绪表现&#xff0c;如一场考试、一次挑战、一个活动等等。这种焦虑情绪的产生并不是一件坏事&#xff0c;相反&#xff0c;焦虑情绪的…

ROS学习笔记(零):ROS与机器人概述

ROS学习笔记&#xff08;零&#xff09;&#xff1a;ROS与机器人概述ROSROS的起源ROS的特点ROS架构设计机器人机器人的定义机器人的组成执行机构驱动系统传感系统控制系统ROS ROS的起源 ROS&#xff08;Robot Operating System&#xff09;是一个广泛使用的机器人操作系统&…

Python图片相册批处理器的设计与实现批量添加图片水印、批量命名等功能

课题研究使用Python语言开发一个包含批量添加图片水印、批量命名等功能的图片批处理程序&#xff0c;功能模块大概包含以下模块&#xff1a; &#xff08;1&#xff09;首页模块&#xff1a;首页是整个软件的初始页面&#xff0c;包含用户登录、注册、关于本软件等功能&#xf…

红日(vulnstack)5 内网渗透ATTCK实战

环境配置 链接&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;l8r7 攻击机&#xff1a;kali2022.03 192.168.135.128(NET模式) win7 192.168.138.136 (仅主机模式) 192.168.135.150 (NET模式) win2008 192.168.138.138 (仅主机模式) web渗透 1.nmap探测目标靶机开…

Qt学习笔记之SQLITE数据库

1. SQLite数据库介绍 SQLite&#xff0c;是一款轻型的数据库&#xff0c;是遵守ACID的关系型数据库管理系统&#xff0c;它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的&#xff0c;而且已经在很多嵌入式产品中使用了它&#xff0c;…

SpringBoot(1)基础入门

SpringBoot基础入门SpringBoot项目创建方式Idea创建SpringBoot官网创建基于阿里云创建项目手工搭建SpringBoot启动parentstarter引导类内嵌tomcat基础配置属性配置配置文件分类yaml文件yaml数据读取整合第三方技术整合JUnit整合MyBatis整合Mybatis-Plus整合DruidSpringBoot是由…

运动健康路线导入,助力用户轻松导航

华为HMS Core运动健康服务支持通过REST API&#xff0c;以GPX文件格式写入用户路线数据&#xff0c;支持导入轨迹&#xff08;Track&#xff09;或路程&#xff08;Route&#xff09;类型的数据&#xff0c;实现用户路线数据在华为运动健康App中的展示效果。 假若与华为运动健…

​selenium+python做web端自动化测试框架与实例详解教程​

下面有详细的代码介绍&#xff0c;如果不是很明白的话&#xff0c;可以看看这套视频&#xff0c;在哔站学习人数超过数万人&#xff01; 在华为工作了10年的大佬出的Web自动化测试教程&#xff0c;华为现用技术教程&#xff01;_哔哩哔哩_bilibili在华为工作了10年的大佬出的W…

分享NVIDIA GTC干货_用软件引领车辆电子架构

随着软件定义功能变得更多&#xff0c;车辆电气/电子架构正在从分布式计算演变为集中式计算。通过将这台集中式超级计算机与人工智能融合在一起&#xff0c;开发模块化软件并创建数据中心基础设施。 电子架构 EEA(Electrical and Electronic Architecture) 首先介绍下EEA&am…

Ansys Zemax | 如何建模离轴抛物面镜

离轴抛物面反射镜是光学工业中一种重要的设计类型。本文演示了如何根据制造商给出的规格设计一个离轴抛物面反射镜&#xff0c;并演示如何使用主光线求解将像面中心与主光线路径对齐。(联系我们获取文章附件) 简介 离轴抛物面反射镜的优点是光束通过反射到达像面途中将不会受…

Winform控件开发(25)——TabControl(史上最全)

一、属性 1、Name 用于获取控件对象 2、AllowDrop 指示用户是否可以拖动数据到TabCotrol上 3、TabCotrol 3.1 Top 沿控件的底部放置选项卡 3.2 Left 沿控件的左边缘放置选项卡 3.3 Right 沿控件的右边缘放置选项卡 3.4 Bottom 沿控件的顶部放置选项卡 4、Anchor 锚定控件…

第18章_MySQL8其它新特性

第18章_MySQL8其它新特性 &#x1f3e0;个人主页&#xff1a;shark-Gao &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是shark-Gao&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f389;目前状况&#xff1a;23届毕业生&#xff0c;…

新一轮商业革命将至,张勇用“敏捷组织”率先交出答卷

一向拥抱变化的阿里再一次拥抱变化。2023年3月28日&#xff0c;阿里宣布了新的组织变革&#xff0c;这应该是迄今为止&#xff0c;阿里最重要的组织变革&#xff0c;其变革力度之大堪称前所未有。具体而言&#xff0c;阿里集团将设立云智能、淘宝天猫商业、本地生活、国际数字商…

口罩检测——环境准备(1)

文章目录前言一、工具及环境要求工具本地环境要求二、工具介绍1.labelimg2.AI Studio3.YOLO2COCO4.PaddleUtils5.paddleyolo三、库的安装总结前言 小编之前做过一期《OpenVINO-yolov5推理》&#xff0c;点开博客自动播放视频甚至有点吵&#xff0c;想过删掉&#xff0c;但是想到…