学习笔记-架构的演进之服务容错策略设计模式-3月day02
文章目录
- 前言
- 断路器模式
- 舱壁隔离模式
- 重试模式
- 总结
- 附
前言
容错设计模式,指的是“要实现某种容错策略,我们该如何去做”。微服务中常见的设计模式包括断路器模式、舱壁隔离模式和超时重试模式等,另外还有流量控制模式等。
断路器模式
断路器模式是微服务架构中最基础的容错设计模式。断路器的思路也简单,就是通过代理(断路器对象)来一对一(一个远程服务对应一个断路器对象)地接管服务调用者的远程请求。断路器会持续监控并统计服务返回的成功、失败、超时、拒绝等各种结果,当出现故障(失败、超时、拒绝)的次数达到断路器的阈值时,它的状态就自动变为“OPEN”。之后这个断路器代理的远程访问都将直接返回调用失败,而不会发出真正的远程服务请求。
通过断路器对远程服务进行熔断,就可以避免因为持续的失败或拒绝而消耗资源,因为持续的超时而堆积请求,最终可以避免雪崩效应的出现。由此可见,断路器本质上是快速失败策略的一种实现方式。

从调用序列来看,断路器就是一种有限状态机,断路器模式就是根据自身的状态变化,自动调整代理请求策略的过程。
断路器一般可以设置为 CLOSED、OPEN 和 HALF OPEN 三种状态:
- CLOSED:表示断路器关闭(请求可正常响应),此时的远程请求会真正发送给服务提供者。断路器刚刚建立时默认处于这种状态,此后将持续监视远程请求的数量和执行结果,决定是否要进入 OPEN 状态。
- OPEN:表示断路器开启,此时不会进行远程请求,直接给服务调用者返回调用失败的信息,以实现快速失败策略。
- HALF OPEN:是一种中间状态。断路器必须带有自动的故障恢复能力,当进入 OPEN 状态一段时间以后,将“自动”(一般是由下一次请求而不是计时器触发的,所以这里的自动是带引号的)切换到 HALF OPEN 状态。在中间状态下,会放行一次远程调用,然后根据这次调用的结果成功与否,转换为 CLOSED 或者 OPEN 状态,来实现断路器的弹性恢复。

这里值得讨论的是OPEN 和 CLOSED 状态的转换条件,不同框架都有各自的偏好设置,如Netflix Hystrix中的默认设置:
当一次调用失败后,如果还同时满足下面两个条件,断路器的状态就变为 OPEN: - 一段时间(比如 10 秒以内)内,请求数量达到一定阈值(比如 20 个请求)。(响应频率)
- 一段时间(比如 10 秒以内)内,请求的故障率(发生失败、超时、拒绝的统计比例)到达一定阈值(比如 50%)。(可用性)
另外,服务熔断和服务降级之间的联系与差别:
断路器做的事情是自动进行服务熔断,属于一种快速失败的容错策略的实现方法。在快速失败策略明确反馈了故障信息给上游服务以后,上游服务必须能够主动处理调用失败的后果,而不是坐视故障扩散。这里的“处理”,指的就是一种典型的服务降级逻辑,降级逻辑可以是,但不应该只是,把异常信息抛到用户界面去,而应该尽力想办法通过其他路径解决问题,比如把原本要处理的业务记录下来,留待以后重新处理是最低限度的通用降级逻辑。
服务降级不一定是在出现错误后才被动执行的,我们在很多场景中谈论的降级更可能是指,需要主动迫使服务进入降级逻辑的情况。比如,出于应对可预见的峰值流量,或者是系统检修等原因,要关闭系统部分功能或关闭部分旁路服务,这时候就有可能会主动迫使这些服务降级。此时服务降级就是出于流量控制的范畴。
舱壁隔离模式
舱壁隔离模式,是常用的实现服务隔离的设计模式。舱壁这个词来自造船业,意思是在每个区域设计独立的水密舱室。
分布式系统中,服务隔离,就是避免某一个远程服务的局部失败影响到全局,而设置的一种止损方案。这种思想,对应的就是容错策略中的失败静默策略。
在调用外部服务可能面临的三大类故障:失败、拒绝和超时中,“超时”引起的故障,尤其容易给调用者带来全局性的风险。这是因为,目前主流的网络访问大多是基于 TPR 并发模型(Thread per Request)来实现的,只要请求一直不结束(无论是以成功结束还是以失败结束),就要一直占用着某个线程不能释放。而线程是典型的整个系统的全局性资源,尤其是在 Java 这类将线程映射为操作系统内核线程来实现的语言环境中。
要解决这类问题,本质上就是要控制单个服务的最大连接数。一种可行的解决办法是为每个服务单独设立线程池,这些线程池默认不预置活动线程,只用来控制单个服务的最大连接数。使用局部的线程池来控制服务的最大连接数,有很多好处,比如当服务出问题时能够隔离影响,当服务恢复后,还可以通过清理掉局部线程池,瞬间恢复该服务的调用。而如果是 Tomcat 的全局线程池被占满,再恢复就会非常麻烦。
但是,局部线程池有一个显著的弱点,那就是它额外增加了 CPU 的开销,每个独立的线程池都要进行排队、调度和下文切换工作。
为应对这种情况,还有一种更轻量的控制服务最大连接数的办法,那就是信号量机制(Semaphore)。如果不考虑清理线程池、客户端主动中断线程这些额外的功能,仅仅是为了控制单个服务并发调用的最大次数的话,我们可以只为每个远程服务维护一个线程安全的计数器,并不需要建立局部线程池。具体做法是,当服务开始调用时计数器加 1,服务返回结果后计数器减 1;一旦计数器的值超过设置的阈值就立即开始限流,在回落到阈值范围之前都不再允许请求了。因为不需要承担线程的排队、调度和切换工作,所以单纯维护一个作为计数器的信号量的性能损耗,相对于局部线程池来说,几乎可以忽略不计。
一般来说,我们会选择将服务层面的隔离实现在服务调用端或者边车代理上,将系统层面的隔离实现在 DNS 或者网关处。
重试模式
故障转移和故障恢复这两种策略都需要对服务进行重复调用,差别就在于这些重复调用有可能是同步的,也可能是后台异步进行;有可能会重复调用同一个服务,也可能会调用服务的其他副本。但是,无论具体是通过怎样的方式调用、调用的服务实例是否相同,都可以归结为重试设计模式的应用范畴。
重试模式适合解决系统中的瞬时故障,简单地说就是有可能自己恢复(Resilient,称为自愈,也叫做回弹性)的临时性失灵,比如网络抖动、服务的临时过载(比如返回了 503 Bad Gateway 错误)这些都属于瞬时故障。
重试模式实现起来并不难,在实践中,我们判断是否应该且是否能够对一个服务进行重试时,要看是否同时满足下面 4 个条件:
- 第一,仅在主路逻辑的关键服务上进行同步的重试。(如果不是关键服务,一般不要把重试作为首选容错方案,尤其不应该进行同步重试。)
- 第二,仅对由瞬时故障导致的失败进行重试。尽管要做到精确判定一个故障是否属于可自愈的瞬时故障并不容易,但我们至少可以从 HTTP 的状态码上获得一些初步的结论。比如,当发出的请求收到了 401 Unauthorized 响应时,说明服务本身是可用的,只是你没有权限调用,这时候再去重试就没有什么意义。
- 第三,仅对具备幂等性的服务进行重试。比如,RESTful 服务中的 POST 请求是非幂等的;GET、HEAD、OPTIONS、TRACE 请求应该被设计成幂等的,因为它们不会改变资源状态;PUT 请求一般也是幂等的,因为 n 个 PUT 请求会覆盖相同的资源 n-1 次;DELETE 请求也可看作是幂等的,同一个资源首次删除会得到 200 OK 响应,此后应该得到 204 No Content 响应。
- 第四,重试必须有明确的终止条件,常用的终止条件有超时终止和次数终止两种:
超时终止。其实,超时机制并不限于重试策略,所有涉及远程调用的服务都应该有超时机制来避免无限期的等待。
次数终止。重试必须要有一定限度,不能无限制地做下去,通常是重试 2~5 次。因为重试不仅会给调用者带来负担,对服务提供者来说也同样是负担,所以我们要避免把重试次数设得太大。
另外,由于重试模式可以在网络链路的多个环节中去实现,比如在客户端发起调用时自动重试、网关中自动重试、负载均衡器中自动重试等等,如果配置不当,可能会带来巨大的负担。
总结
熔断、隔离、重试、降级、超时等概念,都是建立具有韧性的微服务系统的必须的保障措施。那么就目前来说,这些措施的正确运作,主要还是依靠开发人员对服务逻辑的了解,以及根据运维人员的经验去静态地调整、配置参数和阈值。
但是,面对能够自动扩缩(Auto Scale)的大型分布式系统,静态的配置越来越难以起到良好的效果。这就要求,系统不仅要有能力可以自动地根据服务负载来调整服务器的数量规模,同时还要有能力根据服务调用的统计结果,或者启发式搜索的结果来自动变更容错策略和参数。当然,目前这方面的研究,还处于各大厂商在内部分头摸索的初级阶段,不过这正是服务治理未来的重要发展方向之一。
附
此文章为3月Day02学习笔记,内容来源于极客时间《周志明的软件架构课》
相关文章:
学习笔记-架构的演进之服务容错策略设计模式-3月day02
文章目录前言断路器模式舱壁隔离模式重试模式总结附前言 容错设计模式,指的是“要实现某种容错策略,我们该如何去做”。微服务中常见的设计模式包括断路器模式、舱壁隔离模式和超时重试模式等,另外还有流量控制模式等。 断路器模式 断路器…...
【WEB前端进阶之路】 HTML 全路线学习知识点梳理(上)
前言 HTML 是一切Web开发的基础,本文专门为小白整理,针对前端零基础的朋友们,手把手教你学习HTML,让你轻松迈入WEB开发的行列。 首先,感谢 橙子_ 在HTML学习以及本文编写过程中对我的帮助。 文章目录前言一.HTML简介1.…...
mes系统核心业务流程及应用场景介绍
现在许多企业已经开始使用MES系统控制和管理工厂的生产过程,实时监控、诊断和控制生产过程,完成单元集成和系统优化。本文将为大家具体介绍一下MES系统的业务流程。 MES系统业务流程 1、计划调度MES系统承接了ERP订单,开始干预生产。该模块…...
应用统计部分常用公式总结
常见分布函数 常用公式 分位数:P{X>xα}α,P{X≤xα}1−αP\{X>x_\alpha\}\alpha, P\{X\le x_\alpha\}1-\alphaP{X>xα}α,P{X≤xα}1−αE(Xi)E(X)E(X‾)μE(X_i)E(X)E(\overline X)\muE(Xi)E(X)E(X)μE(X2)E2(X)D(X)μ2σ2E(X^2)E^2(X)D(X)\mu^2…...
阿赵的MaxScript学习笔记分享八《文件操作》
大家好,我是阿赵。继续分享MaxScript学习笔记第八篇 。这一篇主要讲文件操作,包括文件的I/O和导入导出。 1、获得3DsMax指定的一些目录路径 如果在电脑上安装了3DsMax软件,那么在文档里面会有一个3dsMax的文件夹,里面有一些3dsMa…...
将项目封装进docker进行迁移或使用
首先要理解docker的基本使用,本文不做过多阐述,博主也对docker没有了解透彻。 这里列一下docker的基本命令: docker info # 查看docker信息 docker -v # 查看docker版本 docker images # 查看docker所有的镜…...
matlab - 特殊矩阵、矩阵求值、稀疏矩阵
学习视频1.特殊矩阵1.1 通用特殊矩阵format % 零矩阵(全0) 幺矩阵(全1) 单位矩阵 % zeros ones eye rand(生成0~1的随机元素) randn(生成均值为1,方差为0的符合正太分布的随机阵)zeros(3) % 3x3的全0方阵 zeros(3, 4) % 3x4的全0矩阵 exA ones(3, 5) % 3x5的…...
Flume使用入门
目录 一. Flume简单介绍 1. Agent 2. Source 3. Sink 4. Channel 5. Event 二. 环境安装 1. 创建日志目录 2. 修改日志配置文件 3.修改运行堆内存 4. 确定日志打印的位置 5. 修改flume使用内存 内存调大 三. 校验flume 1. 安装netcat工具和net-tools工具 2. 判…...
【Servlet篇2】Servlet的工作过程,Servlet的api——HttpServletRequest
一、Servlet的工作过程 二、Tomcat的初始化 步骤1:寻找到当前目录下面所有需要加载的Servlet(也就是类) 步骤2:根据类加载的结果创建实例(通过反射),并且放入集合当中 步骤3:实例创建好之后,调用Servlet的init()方…...
【JAVASE】注解
文章目录1.概述2.JDK内置注解2.1override注解2.2 Deprecated注解3.元注解4.注解中定义属性4.1 属性value4.2 属性是一个数组5. 反射注解6.注解在开发中的作用1.概述 注解,也叫注释,是一种引用数据类型。编译后也同样生成class字节码文件。 语法 [修饰…...
【408之计算机组成原理】计算机系统概述
目录前言一、计算机的发展历程1. 计算机发展的四代变化2. 计算机元件的更新换代3. 计算机软件的发展二、计算机系统层次结构1. 计算机系统的组成2. 冯诺依曼体系结构3. 计算机的功能部件1. 输入设备2. 输出设备3. 存储器4. 运算器5. 控制器三、 分析计算机各个部件在执行代码中…...
1.Spring Cloud (Hoxton.SR10) 学习笔记—基础知识
本文目录如下:一、Spring Cloud基础知识什么是微服务架构?服务拆分 有哪些注意事项?什么是分布式集群?分布式的 CAP 原则?组件 - Spring Cloud 哪几个组件比较重要?组件 - 为什么要使用这些组件?组件 - Na…...
嵌入式开发工具箱【持续更新中】【VMware、Ubuntutftp、nfs、SecureCRT、XShell、Source Insight 4.0】
一、概述 本文主要介绍嵌入式开发过程中需要用到的工具及简单的使用方法。避免在搭建嵌入式开发环境时,需要四处寻找文档,收藏此文章,一文搞定。 大多数嵌入式开发环境是使用Linux作为目标开发系统,所以开发主机一般都是Linux系统…...
深究Java Hibernate框架下的Deserialization
写在前面 Hibernate是一个开源免费的、基于 ORM 技术的 Java 持久化框架。通俗地说,Hibernate 是一个用来连接和操作数据库的 Java 框架,它最大的优点是使用了 ORM 技术。 Hibernate 支持几乎所有主流的关系型数据库,只要在配置文件中设置好…...
微服务一 实用篇 - Docker安装
《微服务一 实用篇 - Docker安装》 提示: 本材料只做个人学习参考,不作为系统的学习流程,请注意识别!!! 《微服务一 实用篇 - Docker安装》《微服务一 实用篇 - Docker安装》0.安装Docker1.CentOS安装Docker1.1.卸载(可选)1.2.安装docker1.3.启动docker…...
JavaSE22-集合2-map
文章目录一、集合概念二、map集合1、Map集合的特点2、HashMap2.1 HashMap特点2.2 创建对象2.3 常用方法2.4 遍历2.4.1 使用entrySet遍历2.4.2 使用keySet遍历3、HashMap的key去重原理一、集合概念 集合就是用于存储多个数据的容器。相对于具有相同功能的数组来说,集…...
【项目精选】病历管理系统设计与实现(源码+视频)
点击下载源码 企业财务管理系统主要用于电子病历来提高医院各项工作的效率和质量,促进医学科研、教学;减轻各类事务性工作的劳动强度,使他们腾出更多的精力和时间来服务于病人。本系统结构如下: 电子病例系统: 病人登…...
如何用Python把篮球和鸡联系起来
文章目录画个球让球转起来画个球 不管篮球和不和鸡联系起来,都首先得有个球,或者说要有一个球面,用参数方程可以表示为 xrcosϕcosθyrcosϕsinθzrsinϕ\begin{aligned} x & r\cos\phi\cos\theta\\ y & r\cos\phi\sin\th…...
【RocketMQ】消息的刷盘机制
刷盘策略 CommitLog的asyncPutMessage方法中可以看到在写入消息之后,调用了submitFlushRequest方法执行刷盘策略: public class CommitLog {public CompletableFuture<PutMessageResult> asyncPutMessage(final MessageExtBrokerInner msg) {// …...
AMBA-AXI(一)burst 传输-INCR/WRAP/Fixed
💡Note:本文是根据AXI协议IHI0022F_b_amba_axi_protocol_spec.pdf(issue F)整理的。主要是分享AXI3.0和4.0部分。如果内容有问题请大家在评论区中指出,有补充或者疑问也可以发在评论区,互相学习ὤ…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
