如果这是第二次看到我的文章,欢迎在文末扫码订阅我哟~
本文长度为3319字,建议阅读9分钟。
当我们工作所在的系统处于分布式系统初期的时候,往往这时候每个服务都只部署了一个节点。
那么在这样的背景下,如果某个服务A需要发布一个新版本,往往会对正在运行的其它依赖服务A的程序产生影响。甚至,一旦服务A的启动预热过程耗时过长,问题会更严重,大量请求会阻塞,产生级联影响,导致整个系统卡慢。
▲点击图片可查看大图
举个夸张的例子来形容:一幢楼的下水管是从最高楼直通到最低楼的,这个时候如果你家楼下的管道口堵住了,那么所有楼上的污水就会倒灌到你家。如果这导致你家的管道口也堵住了,之后又会倒灌到楼上一层,以此类推。
然而实际生活中一旦你发现了这个问题,必然会想办法先避免影响到自己家,然后跑到楼下让他们赶紧疏通管道。此时,避免影响自己家的办法就可被称之为「熔断」。
一、熔断是什么
熔断本质上是一个过载保护机制。这一概念来源于电子工程中的断路器,可能你曾经被这个东西的“跳闸”保护过。
▲图片来源于网络,版权归原作者所有
在互联网系统中的熔断机制是指:当下游服务因访问压力过大而响应变慢或失败,上游服务为了保护自己以及系统整体的可用性,可以暂时切断对下游服务的调用。
做熔断的思路大体上就是:一个中心思想,分四步走。
二、熔断怎么做
首先,需秉持的一个中心思想是:量力而行。因为软件和人不同,没有奇迹会发生,什么样的性能撑多少流量是固定的。这是根本。
然后,这四步走分别是:
-
定义一个识别是否处于“不可用”状态的策略
-
切断联系
-
定义一个识别是否处于“可用”状态的策略,并尝试探测
-
重新恢复正常
定义一个识别是否处于“不正常”状态的策略
相信软件开发经验丰富的你也知道,识别一个系统是否正常,无非是两个点。
-
是不是能调通
-
如果能调通,耗时是不是超过预期的长
但是,由于分布式系统被建立在一个并不是100%可靠的网络上,所以上述的情况总有发生,因此我们不能将偶发的瞬时异常等同于系统“不可用”(避免以偏概全)。由此我们需要引入一个「时间窗口」的概念,这个时间窗口用来“放宽”判定“不可用”的区间,也意味着多给了系统几次证明自己“可用”机会。但是,如果系统还是在这个时间窗口内达到了你定义“不可用”标准,那么我们就要“断臂求生”了。
这个标准可以有两种方式来指定。
-
阈值。比如,在10秒内出现100次“无法连接”或者出现100次大于5秒的请求。
-
百分比。比如,在10秒内有30%请求“无法连接”或者30%的请求大于5秒。
最终会形成这样这样的一段代码。
全局变量 errorcount = 0; //有个独立的线程每隔10秒(时间窗口)重置为0。 全局变量 isOpenCircuitBreaker = false; //do some thing... if(success){ return success; } else{ errorcount++; if(errorcount == 不可用阈值){ isOpenCircuitBreaker = true; } }
切断联系
切断联系要尽可能的“果断”,既然已经认定了对方“不可用”,那么索性就默认“失败”,避免做无用功,也顺带能缓解对方的压力。
分布式系统中的程序间调用,一般都会通过一些RPC框架进行。
那么,这个时候作为客户端一方,在自己进程内通过代理发起调用之前就可以直接返回失败,不走网络。
这就是常说的「fail fast」机制。就是在前面提到的代码段之前增加下面的这段代码。
if(isOpenCircuitBreaker == true){ return fail; } //do some thing...
定义一个识别是否处于“可用”状态的策略,并尝试探测
切断联系后,功能的完整性必然会受影响,所以还是需要尽快恢复回来,以提供完整的服务能力。这事肯定不能人为去干预,及时性必然会受到影响。那么如何能够自动的识别依赖系统是否“可用”呢?这也需要你来定义一个策略。
一般来说这个策略与识别“不可用”的策略类似,只是这里是一个反向指标。
-
阈值。比如,在10秒内出现100次“调用成功”并且耗时都小于1秒。
-
百分比。比如,在10秒内有95%请求“调用成功”并且98%的请求小于1秒。
同样包含「时间窗口」、「阈值」以及「百分比」。
稍微不同的地方在于,大多数情况下,一个系统“不可用”的状态往往会持续一段时间,不会那么快就恢复过来。所以我们不需要像第一步中识别“不可用”那样,无时无刻的记录请求状况,而只需要在每隔一段时间之后去进行探测即可。所以,这里多了一个「间隔时间」的概念。这个间隔幅度可以是固定的,比如30秒。也可以是动态增加的,通过线性增长或者指数增长等方式。
这个用代码表述大致是这样。
全局变量 successCount = 0; //有个独立的线程每隔10秒(时间窗口)重置为0。 //并且将下面的isHalfOpen设为false。 全局变量 isHalfOpen = true; //有个独立的线程每隔30秒(间隔时间)重置为true。 //do some thing... if(success){ if(isHalfOpen){ successCount ++; if(successCount = 可用阈值){ isOpenCircuitBreaker = false; } } return success; } else{ errorcount++; if(errorcount == 不可用阈值){ isOpenCircuitBreaker = true; } }
另外,尝试探测本质上是一个“试错”,要控制下“试错成本”。所以我们不可能拿100%的流量去验证,一般会有以下两种方式:
-
放行一定比例的流量去验证。
-
如果在整个通信框架都是统一的情况下,还可以统一给每个系统增加一个专门用于验证程序健康状态检测的独立接口。这个接口额外可以多返回一些系统负载信息用于判断健康状态,如CPU、I/O的情况等。
重新恢复正常
一旦通过了衡量是否“可用”的验证,整个系统就恢复到了“正常”状态,此时需要重新开启识别“不可用”的策略。就这样,系统会形成一个循环。
▲点击图片可查看大图
这就是一个完整的熔断机制的面貌。了解了这些核心思想,用什么框架去实施就变得不是那么重要了,因为大部分都是换汤不换药。
上面聊到的这些可以说是主干部分,还有一些最佳实践可以让你在实施熔断的时候拿捏的更到位。
三、做熔断的最佳实践
什么场景最适合做熔断
一个事物在不同的场景里会发挥出不同的效果。以下是我能想到最适合熔断发挥更大优势的几个场景:
-
所依赖的系统本身是一个共享系统,当前客户端只是其中的一个客户端。这是因为,如果其它客户端进行胡乱调用也会影响到你的调用。
-
所以依赖的系统被部署在一个共享环境中(资源未做隔离),并不独占使用。比如,和某个高负荷的数据库在同一台服务器上。
-
所依赖的系统是一个经常会迭代更新的服务。这点也意味着,越“敏捷”的系统越需要“熔断”。
-
当前所在的系统流量大小是不确定的。比如,一个电商网站的流量波动会很大,你能抗住突增的流量不代表所依赖的后端系统也能抗住。这点也反映出了我们在软件设计中带着“面向怀疑”的心态的重要性。
做熔断时还要注意的一些地方
与所有事物一样,熔断也不是一个完美的事物,我们特别需要注意2个问题。
首先,如果所依赖的系统是多副本或者做了分区的,那么要注意其中个别节点的异常并不等于所有节点都存在异常,所以需要区别对待。
其次,熔断往往应作为最后的选择,我们应优先使用一些「降级」或者「限流」方案。因为“部分胜于无”,虽然无法提供完整的服务,但尽可能的降低影响是要持续去努力的。比如,抛弃非核心业务、给出友好提示等等,这部分内容我们会在后续的文章中展开。
四、总结
本文主要聊了熔断的作用以及做法,并且总结了一些我自己的最佳实践。
上面的这些代码示例中也可以看到,熔断代码所在的位置要么在实际方法之前,要么在实际方法之后。它非常适合AOP编程思想的发挥,所以我们平常用到的熔断框架都会基于AOP去做。
熔断只是一个保护壳,在周围出现异常的时候保全自身。但是从长远来看平时定期做好压力测试才能更好的防范于未然,降低触发熔断的次数。如果清楚的知道每个系统有几斤几两,在这个基础上再把「限流」和「降级」做好,这基本就将“高压”下触发熔断的概率降到最低了。
Question:
你觉得还有什么时候需要熔断呢?欢迎给我留言交流哦。
相关文章:
微信公众号(首发):跨界架构师。<-- 点击查阅近期热门文章
定期发表原创内容:架构设计丨分布式系统丨产品丨运营丨一些深度思考。
扫码加入小圈子 ↓
相关推荐
在这个关于分布式系统的PPT中,我们可以期待涵盖以下几个重要的知识点: 1. **分布式系统定义与特性**:首先,会介绍分布式系统的概念,包括其组成元素(如服务器、客户端、网络等)以及主要特征,如透明性、并发性...
南京大学作为国内顶尖高校,在计算机科学教育方面有着深厚的底蕴,其研究生级别的分布式系统课程无疑为学生们提供了深入理解和实践这一领域的绝佳平台。这份课件资料集,结合英文教材,为学习者提供了丰富的知识资源...
完整版”很可能是包含一系列实战案例、代码示例、最佳实践的综合教程,可以帮助读者从理论到实践,全面学习分布式系统设计的各种技巧和挑战。 总结来说,构建大规模分布式系统需要深入了解服务化、数据一致性、负载...
以上只是分布式系统原理与范型的一部分核心知识点,实际的教材或报告可能会涵盖更多细节,包括具体的实现技术、最佳实践以及案例研究。通过学习这些内容,可以深入理解分布式系统的工作原理,提升在云计算、大数据、...
在IT行业中,Java语言因其平台无关性...总结来说,Java在大型分布式系统中的应用广泛且深入,从基础的编程模型到高级的框架工具,都能看到Java的身影。理解和掌握这些知识点,对于开发和维护高效的分布式系统至关重要。
首先,书中涵盖了分布式系统的基石——负载均衡。负载均衡是将工作负载分布到多个计算资源上,以提高服务响应速度和系统可用性。它包括网络负载均衡和应用负载均衡,前者主要处理网络层的流量分发,后者则更关注业务...
《大规模分布式存储系统:原理解析与架构实战》与《分布式服务框架原理与实践》这两本书深入探讨了现代IT行业中至关重要的两个主题:分布式存储系统和分布式服务框架。这两者都是构建可扩展、高可用性及高性能应用的...
在“分布式系统——原理与范例”这本书的第三版中,作者深入探讨了这一领域的核心概念、设计模式以及实际应用案例。下面我们将详细阐述分布式系统的相关知识点。 1. **分布式系统定义**:分布式系统由多台物理或...
3. 熔断降级:在分布式系统中,为了避免某个服务节点故障拖垮整个系统,通常需要实现熔断降级机制。Sentinel 允许开发者设定规则,在达到一定条件时自动熔断,从而防止故障蔓延。 4. 系统自适应保护:Sentinel 能够...
《大型电商分布式系统实践》是一套深度探讨电商领域高级技术的资源集合,包含了视频教程与源码,旨在帮助开发者理解并掌握大型电商系统的构建与优化。这套资源主要围绕Java编程语言进行,通过多个课时逐步解析分布式...
分布式Java应用基础与实践是Java开发领域中的一个重要主题,它涉及到如何通过网络将多个独立的计算机节点连接起来,协同处理...无论是初学者还是经验丰富的开发者,都能从中受益,提升自己的分布式系统设计和开发能力。
《分布式服务框架原理与实践(Dubbo,HSF)_李林锋著》这本书深入探讨了分布式服务框架的关键技术和实际应用,主要聚焦于两个知名的开源框架——Dubbo和HSF。这两者都是实现高效率、可扩展的分布式服务的核心工具,尤其...
在“研究生分布式系统课的课件”中,我们可以期待深入学习这个主题的各种核心概念、设计原则以及实际应用。 分布式系统的概念: 1. 分布式计算:这种计算模型涉及多个独立的处理单元(节点)共享数据并执行任务。每...
首先,书中可能会介绍分布式系统的基石——网络通信。这里会讲解TCP/IP协议、HTTP协议以及如何在分布式环境中实现高效的数据传输。还会讨论负载均衡技术,如四层负载均衡和七层负载均衡,以及它们在优化服务分布和...
《网络安全实践指南——CPU熔断和幽灵漏洞防范指引》发布.pdf 该文档涉及的核心知识点主要集中在网络安全领域,特别是针对CPU级别的安全问题。CPU熔断(Meltdown)和幽灵(Spectre)漏洞是2018年公开的重大安全漏洞...
在《分布式系统概念与设计 原书第5版》中,作者详细阐述了分布式系统的理论基础,如CAP定理、BASE原则、Paxos协议以及Raft一致性算法。这些理论为理解分布式服务框架的设计提供了坚实的理论支持。CAP定理指出,在...
Envoy熔断限流实践(一)基于Rainbond插件实现熔断.doc