微服务:熔断,限流,降级

2023-11-03

1 熔断,限流,降级
2 从微观角度思考

2.1 超时(timeout)

在接口调用过程中,consumer调用provider的时候,provider在响应的时候,有可能会慢,如果provider 10s响应,那么consumer也会至少10s才响应。如果这种情况频度很高,那么就会整体降低consumer端服务的性能。

这种响应时间慢的症状,就会像一层一层波浪一样,从底层系统一直涌到最上层,造成整个链路的超时。

所以,consumer不可能无限制地等待provider接口的返回,会设置一个时间阈值,如果超过了这个时间阈值,就不继续等待。

这个超时时间选取,一般看provider正常响应时间是多少,再追加一个buffer即可。

2.2 重试(retry)

超时时间的配置是为了保护服务,避免consumer服务因为provider 响应慢而也变得响应很慢,这样consumer可以尽量保持原有的性能。

但是也有可能provider只是偶尔抖动,那么超时后直接放弃,不做后续处理,就会导致当前请求错误,也会带来业务方面的损失。

那么,对于这种偶尔抖动,可以在超时后重试一下,重试如果正常返回了,那么这次请求就被挽救了,能够正常给前端返回数据,只不过比原来响应慢一点。

重试时的一些细化策略:

重试可以考虑切换一台机器来进行调用,因为原来机器可能由于临时负载高而性能下降,重试会更加剧其性能问题,而换一台机器,得到更快返回的概率也更大一些。

2.2.1 幂等(idempotent)

如果允许consumer重试,那么provider就要能够做到幂等。

即,同一个请求被consumer多次调用,对provider产生的影响(这里的影响一般是指某些写入相关的操作) 是一致的。

而且这个幂等应该是服务级别的,而不是某台机器层面的,重试调用任何一台机器,都应该做到幂等。

2.3 熔断(circuit break)

重试是为了应付偶尔抖动的情况,以求更多地挽回损失。

可是如果provider持续的响应时间超长呢?

如果provider是核心路径的服务,down掉基本就没法提供服务了,那我们也没话说。 如果是一个不那么重要的服务,却因为这个服务一直响应时间长导致consumer里面的核心服务也拖慢,那么就得不偿失了。

单纯超时也解决不了这种情况了,因为一般超时时间,都比平均响应时间长一些,现在所有的打到provider的请求都超时了,那么consumer请求provider的平均响应时间就等于超时时间了,负载也被拖下来了。

而重试则会加重这种问题,使consumer的可用性变得更差。

因此就出现了熔断的逻辑,也就是,如果检查出来频繁超时,就把consumer调用provider的请求,直接短路掉,不实际调用,而是直接返回一个mock的值。

等provider服务恢复稳定之后,重新调用。

2.3.1 简单的熔断处理逻辑

目前我们框架有通过注解使用的熔断器,大家可以参考应用在项目中。

2.4 限流(current limiting)

上面几个策略都是consumer针对provider出现各种情况而设计的。

而provider有时候也要防范来自consumer的流量突变问题。

这样一个场景,provider是一个核心服务,给N个consumer提供服务,突然某个consumer抽风,流量飙升,占用了provider大部分机器时间,导致其他可能更重要的consumer不能被正常服务。

所以,provider端,需要根据consumer的重要程度,以及平时的QPS大小,来给每个consumer设置一个流量上线,同一时间内只会给A consumer提供N个线程支持,超过限制则等待或者直接拒绝。

qps限流 :限制每秒处理请求数不超过阈值。

并发限流:限制同时处理的请求数目。Java 中的 Semaphore 是做并发限制的好工具,特别适用于资源有效的场景。

单机限流:Guava 中的 RateLimiter。

集群限流:TC 提供的 common-blocking 组件提供此功能。

算法:

漏桶算法:漏桶算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水,当水流入速度过大会直接溢出,可以看出漏桶算法能强行限制数据的传输速率。

令牌桶算法:对于很多应用场景来说,除了要求能够限制数据的平均传输速率外,还要求允许某种程度的突发传输。这时候漏桶算法可能就不合适了,令牌桶算法更为适合。
令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。

在 Guava 的 RateLimiter 中,使用的就是令牌桶算法,允许部分突发流量传输。在其源码里,可以看到能够突发传输的流量等于 maxBurstSeconds * qps。

2.4.1 资源隔离

provider可以对consumer来的流量进行限流,防止provider被拖垮。

同样,consumer 也需要对调用provider的线程资源进行隔离。 这样可以确保调用某个provider逻辑不会耗光整个consumer的线程池资源。

2.4.2 服务降级

降级服务既可以代码自动判断,也可以人工根据突发情况切换。

降级,是指牺牲非核心的服务功能,保证核心功能的稳定运行。简单来说,要实现优雅的业务降级,需要将功能实现拆分到相对独立的不同代码单元,分优先级进行隔离。在后台通过开关控制,降级部分非主流程的业务功能,减轻系统依赖和性能损耗,从而提升集群的整体吞吐率。

降级的重点是:业务之间有优先级之分。

2.4.2.1 consumer 端

consumer 如果发现某个provider出现异常情况,比如,经常超时(可能是熔断引起的降级),数据错误,这是,consumer可以采取一定的策略,降级provider的逻辑,基本的有直接返回固定的数据。

2.4.2.2 provider 端

当provider 发现流量激增的时候,为了保护自身的稳定性,也可能考虑降级服务。

比如,1,直接给consumer返回固定数据,2,需要实时写入数据库的,先缓存到队列里,异步写入数据库。

3 从宏观角度重新思考

宏观包括比A -> B 更复杂的长链路。

长链路就是 A -> B -> C -> D这样的调用环境。

而且一个服务也会多机部署,A 服务实际会存在 A1,A2,A3 …

微观合理的问题,宏观未必合理。

下面的一些讨论,主要想表达的观点是:如果系统复杂了,系统的容错配置要整体来看,整体把控,才能做到更有意义。

3.1 超时

如果A给B设置的超时时间,比B给C设置的超时时间短,那么肯定不合理把,A超时时间到了直接挂断,B对C支持太长超时时间没意义。

R表示服务consumer自身内部逻辑执行时间,TAB表示consumer A开始调用provider B到返回的时间 。

那么那么TAB > RB + TBC 才对。

3.2 重试

重试跟超时面临的问题差不多。

B服务一般100ms返回,所以A就给B设置了110ms的超时,而B设置了对C的一次重试,最终120ms正确返回了,但是A的超时时间比较紧,所以B对C的重试被白白浪费了。

A也可能对B进行重试,但是由于上一条我们讲到的,可能C确实性能不好,每次B重试一下就OK,但是A两次重试其实都无法正确的拿到结果。

N标示设置的重试次数

修正一下上面section的公式,TAB > RB+TBC * N。

虽然这个公式本身没什么问题,但是,如果站在长链路的视角来思考,我们需要整体规划每个服务的超时时间和重试次数,而不是仅仅公式成立即可。

比如下面情况:

A -> B -> C。

RB = 100ms,TBC=10ms

B是个核心服务,B的计算成本特别大,那么A就应该尽量给B长一点的超时时间,而尽量不要重试调用B,而B如果发现C超时了,B可以多调用几次C,因为重试C成本小,而重试B成本则很高。 so …

3.3 熔断

A -> B -> C,如果C出现问题了,那么B熔断了,则A就不用熔断了。

3.4 限流

B只允许A以QPS<=5的流量请求,而C却只允许B以QPS<=3的qps请求,那么B给A的设定就有点大,上游的设置依赖下游。

而且限流对QPS的配置,可能会随着服务加减机器而变化,最好是能在集群层面配置,自动根据集群大小调整。

3.5 服务降级

服务降级这个问题,如果从整体来操作,

1,一定是先降级优先级地的接口,两权相害取其轻

2,如果服务链路整体没有性能特别差的点,比如就是外部流量突然激增,那么就从外到内开始降级。

3如果某个服务能检测到自身负载上升,那么可以从这个服务自身做降级。

3.6 涟漪

A -> B -> C,如果C服务出现抖动,而B没有处理好这个抖动,造成B服务也出现了抖动,A调用B的时候,也会出现服务抖动的情况。

这个暂时的不可用状态就想波浪一样从底层传递到了上层。

所以,从整个体系的角度来看,每个服务一定要尽量控制住自己下游服务的抖动,不要让整个体系跟着某个服务抖动。

3.7 级联失败(cascading failure)

系统中有某个服务出现故障,不可用,传递性地导致整个系统服务不可用的问题。

跟上面涟漪(自造词)的区别也就是严重性的问题。

涟漪描述服务偶发的不稳定层层传递,而级联失败基本是导致系统不可用。 一般,前者可能会因为短时间内恢复而未引起重视,而后者一般会被高度重视。

3.8 关键路径

关键路径就是,你的服务想正常工作,必须要完整依赖的下游服务链,比如数据库一般就是关键路径里面的一个节点。

尽量减少关键路径依赖的数量,是提高服务稳定性的一个措施。

数据库一般在服务体系的最底层,如果你的服务可以会自己完整缓存使用的数据,解除数据库依赖,那么数据库挂掉,你的服务就暂时是安全的。

3.9 最长路径

想要优化你的服务的响应时间,需要看服务调用逻辑里面的最长路径,只有缩短最长时间路径的用时,才能提高你的服务的性能。

降级熔断相似点

1.目的一致,都是从可用性可靠性着想,为防止系统的整体缓慢甚至崩溃,采用的技术手段
2.最终表现类似,对于两者来说,最终让用户体验到的是某些功能暂时不可达或不可用
3.粒度一般都是服务级别
4.自治性要求很高,熔断模式一般都是服务基于策略的自动触发,降级虽说可人工干预,但在微服务架构下,完全靠人显然不可能,开关预置、配置中心都是必要手段
降级熔断区别

1.触发原因不一样,服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑
2.自愈能力要求不一样,服务熔断在发生后有自愈能力,而服务降级没有该职责
转:https://www.liangzl.com/get-article-detail-10088.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

微服务:熔断,限流,降级 的相关文章

  • Java new Date() 打印

    刚刚学习 Java 我知道这可能听起来很愚蠢 但我不得不问 System out print new Date 我知道参数中的任何内容都会转换为字符串 最终值是 new Date 返回对 Date 对象的引用 那么它是如何打印这个的呢 Mo
  • 如何在 Play java 中创建数据库线程池并使用该池进行数据库查询

    我目前正在使用 play java 并使用默认线程池进行数据库查询 但了解使用数据库线程池进行数据库查询可以使我的系统更加高效 目前我的代码是 import play libs Akka import scala concurrent Ex
  • 如何找到给定字符串的最长重复子串

    我是java新手 我被分配寻找字符串的最长子字符串 我在网上研究 似乎解决这个问题的好方法是实现后缀树 请告诉我如何做到这一点或者您是否有任何其他解决方案 请记住 这应该是在 Java 知识水平较低的情况下完成的 提前致谢 附 测试仪字符串
  • 使用 Android 发送 HTTP Post 请求

    我一直在尝试从 SO 和其他网站上的大量示例中学习 但我无法弄清楚为什么我编写的示例不起作用 我正在构建一个小型概念验证应用程序 它可以识别语音并将其 文本 作为 POST 请求发送到 node js 服务器 我已确认语音识别有效 并且服务
  • 在 HTTPResponse Android 中跟踪重定向

    我需要遵循 HTTPost 给我的重定向 当我发出 HTTP post 并尝试读取响应时 我得到重定向页面 html 我怎样才能解决这个问题 代码 public void parseDoc final HttpParams params n
  • 反射找不到对象子类型

    我试图通过使用反射来获取包中的所有类 当我使用具体类的代码 本例中为 A 时 它可以工作并打印子类信息 B 扩展 A 因此它打印 B 信息 但是当我将它与对象类一起使用时 它不起作用 我该如何修复它 这段代码的工作原理 Reflection
  • Liferay ClassNotFoundException:DLFileEntryImpl

    在我的 6 1 0 Portal 实例上 带有使用 ServiceBuilder 和 DL Api 的 6 1 0 SDK Portlet 这一行 DynamicQuery query DynamicQueryFactoryUtil for
  • 磁模拟

    假设我在 n m 像素的 2D 表面上有 p 个节点 我希望这些节点相互吸引 使得它们相距越远吸引力就越强 但是 如果两个节点之间的距离 比如 d A B 小于某个阈值 比如 k 那么它们就会开始排斥 谁能让我开始编写一些关于如何随时间更新
  • 如何在PreferenceActivity中添加工具栏

    我已经使用首选项创建了应用程序设置 但我注意到 我的 PreferenceActivity 中没有工具栏 如何将工具栏添加到我的 PreferenceActivity 中 My code 我的 pref xml
  • 从 127.0.0.1 到 2130706433,然后再返回

    使用标准 Java 库 从 IPV4 地址的点分字符串表示形式获取的最快方法是什么 127 0 0 1 到等效的整数表示 2130706433 相应地 反转所述操作的最快方法是什么 从整数开始2130706433到字符串表示形式 127 0
  • 如何将 pfx 文件转换为 jks,然后通过使用 wsdl 生成的类来使用它来签署传出的肥皂请求

    我正在寻找一个代码示例 该示例演示如何使用 PFX 证书通过 SSL 访问安全 Web 服务 我有证书及其密码 我首先使用下面提到的命令创建一个 KeyStore 实例 keytool importkeystore destkeystore
  • 如何在控制器、服务和存储库模式中使用 DTO

    我正在遵循控制器 服务和存储库模式 我只是想知道 DTO 在哪里出现 控制器应该只接收 DTO 吗 我的理解是您不希望外界了解底层域模型 从领域模型到 DTO 的转换应该发生在控制器层还是服务层 在今天使用 Spring MVC 和交互式
  • Google App Engine 如何预编译 Java?

    App Engine 对应用程序的 Java 字节码使用 预编译 过程 以增强应用程序在 Java 运行时环境中的性能 预编译代码的功能与原始字节码相同 有没有详细的信息这是做什么的 我在一个中找到了这个谷歌群组消息 http groups
  • 如何从指定日期获取上周五的日期? [复制]

    这个问题在这里已经有答案了 如何找出上一个 上一个 星期五 或指定日期的任何其他日期的日期 public getDateOnDay Date date String dayName 我不会给出答案 先自己尝试一下 但是 也许这些提示可以帮助
  • 如何从泛型类调用静态方法?

    我有一个包含静态创建方法的类 public class TestClass public static
  • 玩!框架:运行“h2-browser”可以运行,但网页不可用

    当我运行命令时activator h2 browser它会使用以下 url 打开浏览器 192 168 1 17 8082 但我得到 使用 Chrome 此网页无法使用 奇怪的是它以前确实有效 从那时起我唯一改变的是JAVA OPTS以启用
  • 声明的包“”与预期的包不匹配

    我可以编译并运行我的代码 但 VSCode 中始终显示错误 早些时候有一个弹出窗口 我不记得是什么了 我点击了 全局应用 从那以后一直是这样 Output is there but so is the error The declared
  • 在 Maven 依赖项中指定 jar 和 test-jar 类型

    我有一个名为 commons 的项目 其中包含运行时和测试的常见内容 在主项目中 我添加了公共资源的依赖项
  • 使用 JMF 创建 RTP 流时出现问题

    我正处于一个项目的早期阶段 需要使用 RTP 广播DataStream创建自MediaLocation 我正在遵循一些示例代码 该代码目前在rptManager initalize localAddress 出现错误 无法打开本地数据端口
  • 如何修复 JNLP 应用程序中的“缺少代码库、权限和应用程序名称清单属性”?

    随着最近的 Java 更新 许多人都遇到了缺少 Java Web Start 应用程序的问题Codebase Permissions and Application name体现属性 尽管有资源可以帮助您完成此任务 但我找不到任何资源综合的

随机推荐

  • wc命令

    Linux wc命令用于计算字数 利用wc指令我们可以计算文件的Byte数 字数 或是列数 若不指定文件名称 或是所给予的文件名为 则wc指令会从标准输入设备读取数据 语法 wc clw help version 文件 参数 c或 byte
  • 配置方法数超过 64K 的应用

    https developer android com studio build multidex html 配置方法数超过 64K 的应用 本文内容 关于 64K 引用限制 Android 5 0 之前版本的 Dalvik 可执行文件分包
  • 《区块链基础知识25讲》-第十四讲-存储交易数据

    目标 是利用区块链技术 以有序的方式维护交易数据的整个历史记录 挑战 是如何按交易顺序存储发生的交易数据 并且找到一种能够快速检测到交易数据发生变化的方法 通过创建一个交易数据库 并维护一个保留了将交易添加到交易数据库中顺序的目录来实现对历
  • 深入理解Java IO流:高效数据输入输出的利器

    文章目录 简介 基本概念 字节流 字节输出流 OutputStream 抽象类 字节输出流的子类 FileOutputStream 字节输入流 InputStream 抽象类 字节输入流的子类 FileInputStream 字符流 字符输
  • css开启第一张简单式网页图

    参考链接 https www runoob com try try cdnjs php filename trycss website layout blog 我是参考上述链接 稍微做些修改 然后如下
  • poi 顺序解析word_POI解析word文档,支持DOC和DOCX版本

    一 简介 Apache POI是一个开源的利用Java读写Excel WORD等微软OLE2组件文档的项目 最新的3 5版本有很多改进 加入了对采用OOXML格式的Office 2007支持 如xlsx docx pptx文档 二 POI组
  • fetch详细讲解

    fetch 是一种网络通信协议 用于在客户端和服务器之间传输数据 该协议使用 HTTP 请求和响应进行通信 与传统的 AJAX 方式相比 fetch 更加简单易用 并提供了许多现代化的功能 1 fetch 介绍 使用 fetch 可以方便地
  • Qt重新加载内存中的QSS样式

    什么叫重新加载内存中的QSS样式 当QSS被封装到QSS文件时 需要使用这个QSS 需要将其读出来 理论上说 读出来后 其在程序结束之前应该就一直保存在内存中 当我们给控件设置一个动态属性 在该QSS中存在不同属性 不同样式的时候 在程序运
  • benchmark woa wsl arm64 go

    code 利用比特币的pow算法的简易版本对woa arm64 与 woa wsl arm64 版本的go进行benchmark测试 源码随便从网上摘的 这个东西学习过比特币区块链的人都写过 大同小异 package main import
  • FTP工具upload失败,上载失败

    目标服务器FTP没开 去目标服务器的终端 LInux 输入一下 service vsftpd start ps ef grep ftp
  • 【Linux基础】第29讲 Linux用户和用户组权限控制命令(一)

    1 useradd 添加新用户 注意 当前用户必须有添加用户的权限 1 基本语法 useradd 用户名 功能描述 添加新用户 2 案例 root sue virtual machine usr local useradd hadoop 2
  • 完美解决ModuleNotFoundError: No module named pip._internal

    解决方案 命令1 1 curl https bootstrap pypa io get pip py o get pip py 命令2 2 python get pip py force reinstall 如果提示curl不是内部或外部命
  • PING 192.168.5.13 (192.168.5.13 ) 56(84) data bytes后长时间不响应

    PING 192 168 5 13 192 168 5 13 56 84 data bytes后长时间不响应 原因 没有关闭电脑的防火墙 解决办法 关闭电脑防火墙 解决后 ping通了
  • 虚幻4学习笔记(8)动手制作一个小游戏

    动手制作一个小游戏 新节点介绍 前期准备 搭建场景 门蓝图 灯蓝图 创建关卡蓝图 B站UP谌嘉诚课程 https www bilibili com video BV164411Y732 新节点介绍 前期准备 搭建场景 H隐藏 场景中当前选中
  • Caffe 在 win10 环境下配置

    参考 Caffe windows10下caffe安装 Windows 10下安装配置Caffe并支持GPU加速 整了好几天 终于实现 windows 环境下的 caffe 编译 实现 win10 caffe vs2013 anaconda2
  • windows10 安装wsl2+docker+php+nginx+mysql

    第一步在windows10 上安装docker 可视化桌面 第二步确定本地电脑开启虚拟化 同时确认下方图内容已经勾选 在cmd下使用命令 wsl install 安装wsl2 因 wsl2 默认安装ubuntu系统 如果安装wsl2后没有安
  • 最简单替换jar包class文件

    jar包右击 打开方式 360压缩 找到需要替换的地址 直接拖进去替换即可 方便快捷
  • 多元分类预测

    文章目录 效果一览 文章概述 部分源码 参考资料 效果一览 文章概述 多元分类预测 Matlab 基于K近邻算法 KNN 的数据分类预测 多特征输入模型 多特征输入单输出的二分类及多分类模型 程序内注释详细 直接替换数据就可以用 程序语言为
  • pytorch: torch.max() 使用与理解

    在使用 pytorch 进行训练时 会使用使用到改行代码 predict torch max outputs data 1 1 其中 output 为模型的输出 该函数主要用来求 tensor 的最大值 每次看到都不太理解 torch ma
  • 微服务:熔断,限流,降级

    1 熔断 限流 降级 2 从微观角度思考 2 1 超时 timeout 在接口调用过程中 consumer调用provider的时候 provider在响应的时候 有可能会慢 如果provider 10s响应 那么consumer也会至少1