谷歌事故回顾:https://news.shulie.io/?p=5103
鲁棒性(robustness)其意思是健壮和强壮,就是系统的健壮性。它是指一个程序中对可能导致程序崩溃的各种情况都充分考虑到,并且作相应的处理,在程序遇到异常情况时还能正常工作,而不至于死机。
所谓“鲁棒性”,是指控制系统在一定(结构,大 小)的参数摄动下,维持某些性能的特性。根据对性能的不同定义,可分为稳定鲁棒性和性能鲁棒性。以闭环系统的鲁棒性作为目标设计得到的固定控制器称为鲁棒控制器。
比如说,计算机软件在输入错误、磁盘故障、网络过载或有意攻击情况下,能否不死机、不崩溃,就是该软件的鲁棒性。相应的处理,例如有异常处理、捕获异常、避免发生越界读写等等,这些要靠程序员的经验来完成。
容错(Fault Tolerance)指在计算机系统的软件、硬件发生故障时,保证计算机系统中仍能工作的能力,通俗的讲就是发生故障时,系统还能继续运行,容错的目的是发生故障时,系统的运行水平可能有所下降,但是依然可用,不会完全失败。
常见的容错设计技术分别是恢复快设计,N版本程序设计和冗余设计。
- 恢复块设计:选择一组操作作为容错设计单元,从而把普通的程序块变成恢复块。一个恢复块包含若干个功能相同、设计差异的程序块文本,每一时刻有一个文本处于运行状态。一旦该文本出现故障,则用备份文本加以替换,从而构成“动态冗余”。
- N版本程序设计:N版本的核心是通过设计出多个模块或不同版本,对于相同初始条件和相同输入的操作结果,实行多数表决,防止其中某一模块/版本的故障提供错误的服务,以实现软件容错。
- 冗余设计:冗余设计技术实现原理是在一套完整的软件系统之外,设计一种不同路径,不同算法或不同实现方法的模板或系统作为备份,在出现故障时可以使用冗余的部分进行替换,从而维持软件系统的正常运行。
举个例子:飞机有四个引擎,如果一个引擎坏了,剩下三个引擎,还能继续飞,这就是”容错”。同样的,汽车的一个轮子扎破了,剩下三个轮子,也还是勉强能行驶。
容错的设计有个基本原则,就是面向失败设计“Design for Failure”。为了避免出现“千里之堤溃于蚁穴”这种情况,在设计上需要考虑到各种边界场景和对于服务间调用出现的异常或延迟情况,同时在架构设计和编程时也要考虑周到,这一切都是为了达到以下目标:
- 一个依赖服务的故障不会严重破坏用户的体验。
- 系统能自动或半自动处理故障,具备自我恢复能力。
面向失败设计
在分布式系统中,出现故障是不可避免,故面向失败设计显的尤为重要,倒逼我们在架构设计时要有这种思想,对可能出现各种边界场景情况考虑周到,一般面向失败设计可以参考如下,例如冗余、故障转移、隔离、超时、重试。
1.冗余与故障转移
冗余设计是在一套完整的软件系统之外,设计一种不同的路径,不同的算法或不同的实现方法的模块或系统作为备份,在出现故障时可以使用冗余的部分进行替换,从而维持软件系统的正常运行。多余的重复或啰嗦内容(包括信息、语言、代码、结构、服务、软件、硬件等等)均称为冗余。冗余有两层含义,第一层含义是指多余的不需要的部分,第二层含义是指人为增加重复部分,其目的是用来对原本的单一部分进行备份,以达到增强其安全性的目的,这在信息通信系统当中有着较为广泛的应用,可以从两方面理解:
- 第一层:表示多余的不需要的部分,举个例子:一个数据库可以存储100万条数据,但是我们可以设置最多存储80万条,剩余的20万就是冗余,这样就提高一定的读写性能。那如果达到80万之后还要增加数据怎么办?可以通过更换硬件、增加数据库数量、分库分表等方式来解决。
- 第二层:是说增加重复部分,上面所说的集群可以说是一种冗余
总结:集群是一种冗余,但是冗余可不一定是集群
故障转移是指当活动的服务或应用意外终止时,快速启用冗余或备用的服务器、系统、硬件或者网络接替它们工作。故障转移与交换转移操作基本相同,只是故障转移通常是自动完成的,没有警告提醒手动完成,而交换转移需要手动进行。对于要求高可用和高稳定性的服务器、系统或者网络,系统设计者通常会设计故障转移功能。
高可用的核心是冗余,只有冗余还是不够的,原因是每次出现故障需要人工介入,那么恢复成本和复杂度势必会增加,所以一般通过冗余+自动故障转移来实现系统的高可用。
例如:访问MySQL的容错设计写操作:如果master异常,直接抛异常;读操作:如果slave有多个,先选择其中一个slave,如果获取连接失败,再选择其他的slave,如果全部不可用,最后选择master。
1.1 冗余好处
冗余最大的好处就是避免单点故障,一旦某个机器出现故障时,自动故障转移,切换到多余的机器,从而为其提供服务,一个好的系统设计应该是分布式和集群的结合,先分布式再集群,设置适当的冗余, 具体实现就是业务拆分成很多子业务,然后针对每个子业务进行集群部署,这样某个子业务如果出了问题, 整个系统完全不会受影响。
1.2 冗余原则
平衡主节点故障允许时间T1和主备节点切换时间T2。 由于对于整个系统而言,需求被定位在节点的故障允许时间T。 当T1太长、T2太短时,系统用来监视主备节点运行状态的消耗就少些, 但对主备节点的切换性能要求高,这只有在主备节点间数据同步很充分的时候, 才能做到,所以就提高了对数据同步要求。
减少需要同步的数据量。一方面,对构件信息进行良好归类,分离出静态信息和可以自行获得的信息, 不需要对这些信息进行同步。另一方面,增大构件的尺寸,把内部联系紧密的构件聚合成较大的构件, 这样就减少了需要跟外部交换的信息,也可以减少需要同步的数据量。
1.3 被动式冗余
基于失败重试原理,在可用的服务提供者之间重试,直到找到一个可用的提供者。被动式冗余是简单的, 但也有很大的局限性,它要求冗余节点只是作为信息的处理者, 完全作为C/S架构中的S,而不可能作为信息的发起者。这类冗余在事务处理系统(MIS)中比较常见, 因为这类系统总是响应用户的操作,而很少会有自动收集信息并处理的业务。
1.4 主动式冗余
主备节点间设有交换运行状态的通讯通道,由他们自行协商何时进行主备切换,可以称为自控方式。另一种是基于一个中心的冗余控制器,冗余控制器分别与主备节点通讯,并决定何时进行主备切换,可以称为集控方式。
小结:
冗余是对软件系统元素,多余的重复,目的是在出现故障时可以使用冗余的部分进行替换,自动故障转移,从而维持软件系统的正常运行,冗余的架构设计前提是服务是无状态,在故障替换时可直接替换,如果服务是有状态,针对该状态进行特殊设计或假设该服务故障之后,状态数据如何恢复,方法论上高可用是通过冗余+自动故障转移来实现的。整个互联网分层系统架构的高可用,通过对每一层的冗余+自动故障转移来实现的。
2. 隔离
在造船行业,往往使用此类模式对船舱进行隔离,利用舱壁将不同的船舱隔离起来,这样如果一个船舱破了进水,只损失一个船舱,其它船舱可以不受影响,而借鉴造船行业的经验,这种模式也在软件行业得到使用。
隔离,是对什么进行隔离呢?是对系统、业务所占有的资源进行隔离,限制某个业务对资源的占用数量,避免一个业务占用整个系统资源,对其他业务造成影响。隔离可以对业务的资源、故障隔离。资源隔离目标就是保证该业务对资源有足够的的使用权,避免其他业务占用该资源,资源是单独为其准备和预留的。
业务隔离本身其实就某种意义上的故障隔离,将业务按照业务属性功能或者用户群体进行拆分隔离,故障隔离就是把故障通过某种方式与其正常的模块进行隔离,以保证其某一模块出现故障后,不影响其他的模块,其实,我们生活有很多故障隔离的例子,比如交通。一辆车就类似于分布式系统中的一个模块,当一辆车在高速公路上出现故障后,我们通常会将其停靠在紧急车道,或者在其前后设置故障指示牌,以防止其他车辆与其相撞,引起更大的交通事故。这种将故障车辆停靠在路边紧急车道或设置故障指标牌的方法,就是一种故障隔离。
2.1 隔离目的
减少故障的方式有多种,包括系统优化、监控、风险扫描、链路分析、变更管控、故障注入演练、故障隔离等。故障隔离是其中一种手段,并且要求在系统设计时就需要考虑清楚。
从系统的角度看
故障隔离是指在系统设计的时候,要尽可能考虑故障的情况,当存在依赖关系的系统、系统内部组件或系统依赖的底层资源发生故障后,采取故障隔离措施可以将故障范围控制在局部,防止故障范围扩大,增加对上层系统可用性带来的影响。并且当故障发生时,我们能够快速定位故障源,为后续的故障恢复提供必要条件。
从业务的角度看
故障隔离是为保障重点业务和保障重点客户,本质上弃卒保车的做法。所以,各个业务域需要定义出哪一些是重点业务和客户。区分办法视各个业务而定。有一种区分是按核心功能、重要功能、非关键功能三个等级来区分。比如,对于支付业务来说,支付肯定是一级业务,像营销、限额等是二级业务,而运营管理功能是三级业务。
2.2 隔离范围
隔离是指系统按照一定的原则划分为若干个服务模块,各个模块之间相对独立,无强依赖。当有故障发生时,能将问题和影响隔离在某个模块内部,而不扩散风险,不波及其它模块,不影响整体的系统服务。
大体上讲,隔离级别按粒度从小到大,可以分为线程池隔离、进程隔离、模块隔离、应用隔离、机房隔离,数据库的读写分离、动静隔离、热点隔离。
- 线程池隔离:不同的业务使用不同的线程池,避免低优先级的任务阻塞高优先级的任务。或者高优先级的任务过多,导致低优先级任务永远不会执行,Hystrix是Netflix开源的一款容错框架,包含常用的容错方法:线程隔离、信号量隔离、降级策略、熔断技术。
- 进程隔离:在业务发展初期,规模可能不大,开发的系统可能是单体架构,所有功能模块都在一个应用进程中运行。这样,某个模块出现问题时,可能会直接导致整个系统不可用。现在的方案都是通过微服务架构,根据业务功能将系统拆分成多个子系统,即一个个独立运行的微服务进程。Linux 中有用于进程资源隔离的 Linux CGroup,通过物理限制的方式为进程间资源控制提供了简单的实现方式,为 Linux Container 技术、虚拟化技术的发展奠定了技术基础
- 模块隔离、应用隔离:很多线上故障的发生源于代码修改后,测试不到位导致。按照代码或业务的易变程度来划分模块或应用,把变化较少的划分到一个模块或应用中,变化较多的划分到另一个模块或应用中。减少代码修改影响的范围,也就减少了测试的工作量,减少了故障出现的概率。
- 机房隔离:主要是为了避免单个机房网络问题或断电。
- 读写分离:将对实时性要求不高的读操作,放到 DB 从库上执行,有利于减轻 DB 主库的压力;将一些耗时离线业务 SQL 放到 DB 从库上执行,能够减少慢 SQL 对 DB 主库的影响,保证线上业务的稳定可靠。
- 动静隔离:在高并发系统中,我们可以将静态资源和动态资源分离,一般的做法是将静态资源放在CDN节点上,用户访问页面时,会先从CDN缓存中获取静态资源,如果没有获取到,则回源到后端服务器获取。
- 热点隔离:秒杀,抢购这种流量就是典型的热点流量,而这种热点我们是能提前知道的,所以可以将秒杀服务做成独立系统进行隔离,从而保证真个系统的可用性。
在实际应用场景中,可按业务或服务进行拆分隔离、也可以按照用户级别隔离,有很多这方面隔离的例子。
例如:服务隔离,假设某个电商平台,可以将其中的 用户系统、订单系统、支付系统、仓储系统 都分别进行独立隔离,这样做就是从服务层面实现了故障的隔离效果。
再例如:用户隔离,假设某平台,可以针对TOB、TOC两种用户群体进行隔离,原因是两种用户群体业务场景和所关心的点都都是不同的,如:TOC的用户,大多数更多的关心自己的数据,故所有的设计都有本身的用户ID,再如:TOB的用户,可能关注所有的用户,或者在某个场景下具体哪些用户有什么不同的行为。
2.3 隔离好处
- 限制故障的影响范围,采用了故障隔离的架构,每个子模块的故障至影响它本身而不会波及到其他模块。
- 便于故障定位和分析,相对于一个大而复杂的系统而言,小的隔离模块更简单,一旦出现故障,也更容易分析和定位。
- 故障隔离是系统扩展的一种措施,我们经常采用的垂直分片理论上就是一种故障隔离方式。
- 缩短开发时间,一个复杂的系统能够分成很多功能独立的子模块,这些子模块可以分配给不同的研发人员进行并行开发,一方面可以加快系统的总体开发时间,另一方面,研发人员专注于某个模块让代码的质量更高。
2.4 隔离原则
- 不可越界:能在隔离模块内完成的逻辑,就尽量不要跨模块调用,减少依赖。
- 不可共享:数据和资源能独享的就尽量不要共享,不然很容易造成隔离失效。
- 考虑效率:设计隔离模块的时候,要根据业务情况而定,充分的考虑到未来的拓补结构,减少调用效率的损失。
- 考虑颗粒度:隔离模块设计的大小问题,过大和过小都不合适,需充分考虑。
- 全面监控:既然服务或用户进行隔离了,那么系统的复杂度肯定是比之前要高了,那么针对多服务的全链路监控是必不可少的,先于用户发现问题。
小结:
隔离是借鉴了造船行业中的舱壁模式一种思想,这样做的好处是当系统某处出现故障,可以进行将故障进隔离,防止该故障影响了整个系统,将损失降到最低,避免影响整个系统。前提是要在架构设计的过程中,对业务和服务做好隔离。
3. 超时
超时模式,是一种最常见的容错模式,常见的有设置网络连接超时时间,一次RPC的响应超时时间等。在分布式服务调用的场景中,它主要解决了当依赖服务出现建立网络连接或响应延迟,不用无限等待的问题,调用方可以根据事先设计的超时时间中断调用,及时释放关键资源,如Web容器的连接数,数据库连接数等,避免整个系统资源耗尽出现拒绝对外提供服务这种情况,所有的调用必须设置超时时间,不设置超时时间请求有可能陷入长期等待,甚至有可能导致整个服务不可用。例如:数据库操作、缓存、消息队列等等,均需要设置超时时间。
3.1 超时分析
超时分析一般情况下需要根据接口的性能状况及资源使用情况,通过压测的得出P99分位的耗时,线上正常的响应时间 P99.9 代表该系统稳定状态下的值,超出该值意味着系统出现异常,该值作为参考值,也可根据线上实际请得出每日或者每周高峰期时刻的P99分位耗时,并添加一定的Buffer,得出相对合理的值。
3.2 超时治理
超时治理通过一系列手段来帮助检测超时设置是否合理,及超时时间是否可以有进一步的优化空间,我们应当规范设置调⽤超时时间。设置超时时间的意义, 是在极端情况下,采⽤主动的快速失败策略,使得资源消耗与释放资源之间达到平衡,避免调⽤双⽅因资源耗尽⽽宕机。超时时间设置不当引发,容易引发⽣产故障。
超时治理的手段可以通过调用链来对整个链路的响应时间进行分析,得出调用链中各个关键路径的耗时时间。在通过日或者周的得出P99百分耗时,得出该关键路径稳定状态下的值。超时时间可配置中心动态对关键路径的超时时间设置。如下图,假设用户请求服务A,会经过01、02、03、04、05、06链路才能够完成此次请求,最终将数据返回给用户,那么每一个路径耗时情况均不同,这种情况就可以通过调用链分析出每个调用链在稳定状态下P99的值,在增加一定的Buffer即可。在这种情况下对超时治理也比较友好,可通过配置中心来动态设置。
3.2.1设置过长影响
超时时间过⻓容易引起降级失效、系统崩溃、连接池爆满等问题。如图,例如课程API服务正常调用可能都在200MS内完成,假设当前设置1S超时,那么可能会导致课程Service服务出现问题,课程API服务会大量的和课程Service建立连接,并等待,原因是超时时间是1S,很可能会发⽣串联雪崩,服务内部通信建议设置200MS左右较为合理。
3.2.2设置过短影响
超时时间设置过短,实际⽣产中容易因⽹络抖动⽽告警频繁,造成服务不稳定等⽤户体验问题。如图,网管服务到课程API服务的超时时间是200MS,但是课程API服务到课程Service服务的超时时间300MS,假设课程Service服务300MS内返回数据给课程API服务,此时网管服务到课程API的连接已经断了,原因是下游超时大于上游超时时间。
3.2.3 合理设定
合理设置超时时间,对系统的稳定来⾔,非常重要,我们可参考以下超时时间设置原则:
- 上游超时时间必须大于下游超时时间。
- 服务层级不建议超过3层,服务内部通信或者中间件通信,建议超时时间设置200MS左右。
- 超时时间设置建议参考P99分位耗时,再增加一定的buffer。
- 哪里有IO的地方,哪里就必须要设置超时时间。
- 对用户来说,响应时间可接受2S以内,故超时设置2S,响应时间如果长的话,用户可能就流失了。
小结:
关于所有IO操作几乎都存在超时,大多数框架本身都设置有默认的超时时间,不同场景下超时配置策略是不一样的,对于超时配置、合理性,也是需要我们通过手段帮助我们管控,检测合理性,这种手段称之为超时治理,不能说配置了就完事了,前期是可以通过经验和分析得出来,后期通过超时治理、验证,多种方式相互结合进行优化,避免双方资源消耗,引发稳定性相关的问题。
4. 重试
当应用程序尝试连接到服务或网络资源时,使应用程序能够通过以透明方式重试失败的操作来处理临时故障,这可以提高应用程序的稳定性,重试是一种保障业务运行的容错机制,通过重试机制可以提高请求的最终成功率,减少故障影响,让系统运行更稳定。
4.1重试风险
重试是存在一定的风险,原因是重试配置不合理,很有可能将流量放到几倍,最终会导致雪崩,重试需要慎重考虑重试策略、重试场景;对于POST,PUT,DELETE操作重试的前提是要确保该操作的幂等性,防止出现脏数据。
4.1.1单点重试风险
单点重试风险:例如,A服务请求B服务,未设置重试次数,直到重试成功为止,很容易将下游服务打垮。
为了防止单点重试风险,故要我们进行单点重试进行限制,一个服务不能不受限制的重试下游,很容易造成下游被打垮,除了限制用户设定的重试次数上限外,更重要的是限制重试请求的成功率。
解决思路:基于断路器的思想,限制请求失败/请求成功的比率,给重试增加熔断功能,结合滑动窗口算法来实现。这样就可以根据窗口内的失败/成功来决策是否需要熔断,重试阈值。
4.1.2 链路重试风险
链路重试风险:例如,如果A服务请求B服务,B服务请求C服务,重试次数配置为3次,重试策略无,假如B服务突然处理A服务的请求超时,出现慢查询了,那么会重试3次,假设有10万的流量,那么B服务接受压力可能是30万的,而之前的容量预备了15左右的量,那么此时就会出现B服务挂掉,假设B再请求C服务,那么可能会导致整个服务都挂掉。
为了防止链路重试风险,故要我们进行链路重试进行限制,虽然有了重试熔断之后,重试不再是指数增长(每一单节点重试扩大限制了 1.1 倍),但还是会随着链路的级数增长而扩大调用次数,因此还是需要从链路层面来考虑重试的安全性。
解决思路:链路层面的防重试风暴的核心是限制每层都发生重试,理想情况下只有最下一层发生重试。
Google SRE 中指出了 Google 内部使用特殊错误码的方式来实现:
- 统一约定一个特殊的 status code ,它表示:调用失败,但别重试。
- 任何一级重试失败后,生成该 status code 并返回给上层。
- 上层收到该 status code 后停止对这个下游的重试,并将错误码再传给自己的上层。
这种方式理想情况下只有最下一层发生重试,它的上游收到错误码后都不会重试,链路整体放大倍数也就是 r 倍(单层的重试次数)。但是这种策略依赖于业务方传递错误码,对业务代码有一定入侵,而且通常业务方的代码差异很大,调用 RPC 的方式和场景也各不相同,需要业务方配合进行大量改造,很可能因为漏改等原因导致没有把从下游拿到的错误码传递给上游。
4.2重试场景
在分布式系统中,出现错误或故障很常见,因此应当将应用程序设计为能够优雅地以透明方式处理它们。 这可以尽量降低错误可能会给应用程序正在执行的业务任务带来的影响,重试场景包括可重试和不可重试两种场景,不是所有的场景都可以重试的。
4.2.1可重试
可重试场景,暂时性错误可以自动修复,这类错误包括组件和服务瞬间断开网络连接、服务暂时不可用,或者当服务繁忙时出现超时。这些错误通常可以自己修复,如果在延迟合适的时间后重新执行触发了错误的操作,该操作可能会成功。
例如,处理大量并发请求的数据库服务可以实现限制策略,该策略会暂时拒绝任何后续请求,直到其工作负荷得以减轻。 尝试访问该数据库的应用程序可能无法连接,但如果它在延迟一段时间后再次尝试,则可能会成功。
实际项目场景包括:网络超时、服务器繁忙等。
4.2.2不可重试
不可重试场景,对于有些错误是无法自动修复的,如果错误表明故障不是暂时性的或者在重新执行的情况下不可能成功,则应用程序应当取消操作并报告异常。
例如,对于因为提供了无效的凭据而导致的身份验证失败,无论尝试多少次,身份验证都不可能成功。
实际项目场景包括:业务自定义错误、权限、鉴权,流控,服务能力上限等。
4.3 重试策略
对于一些暂时性的错误,如网络抖动等,可能立即重试还是会失败,通常等待一小会儿再重试的话成功率会较高,并且也可能打散上游重试的时间,较少因为同时都重试而导致的下游瞬间流量高峰。决定等待多久之后再重试的方法叫做退避策略,我们实现了常见的退避策略,如:
- 线性退避:每次等待固定时间后重试。
- 随机退避:在一定范围内随机等待一个时间后重试。
- 指数退避:连续重试时,每次等待时间都是前一次的倍数。
4.4重试原则
- 请慎重考虑重试场景,对重试场景决策。应当对重试策略进行调整以匹配应用程序的业务要求和故障性质。 对于某些非关键操作,最好是快速失败而不是重试多次并影响应用程序的吞吐量。
- 请考虑操作是否是幂等的。如果是,则可以放心地进行重试。 否则,重试可能会导致操作执行多次并产生意外的副作用(脏数据)。
- 增加重试失败监控。如果某个请求在进行大量的重试后失败,则应用程序最好立刻报警到相关责任人。
- 请合理配置重试策略。某些异常表明故障可以快速解决,而另一些异常表明故障会持续较长时间。 根据异常类型为重试策略调整重试尝试之间的时间间隔会起作用。
- 请确保针对各种故障状况充分测试重试代码。 请检查并确保它不会严重影响应用程序的性能或可靠性、不会导致服务和资源过载,不会导致争用状况或瓶颈。
小结:
重试机制在某些情况下可帮助我们提升成功率,减少故障影响,让系统运行更稳定,前提是我们能够对重试风险、重试场景、重试策略、重试机制有清楚的认识,能够合理的配置,否则重试机制可能不会帮助我们提升成功率,还会带来服务打垮、雪崩等情况,造成严重事故,因此对重试机制需要慎重并合理配置。
5.一些内容补充
5.1 故障转移相关
因为网络问题和系统中的变更,服务通常会出现故障。然而,这些故障中断大多是暂时的,这要归功于自我修复和高级负载平衡的功能,我们应该找到一个解决方案,能使服务即使在出现故障的时候也能工作。这就是故障转移缓存(Failover Caching),它能帮助为我们的应用提供必需的数据。
失效转移缓存通常使用两个不同的过期日期:其中更短的日期指示在正常情况下能使用缓存的时间,而更长的一个日期则指示在故障失效的时候,能使用缓存中的数据时长。
故障转移缓存,特别需要提醒的是,只有当提供过时的数据比没有数据更好的情况下,才能使用故障转移缓存,要设置缓存和故障转移缓存,可以在HTTP中使用标准响应头。
例如,使用 max-age 属性可以指定资源被视为有效的最大时间。使用 stale-if-error 属性,您可以明确在出现故障的情况下,依旧可以从缓存中获取资源的最大时间。
5.2超时、重试相关
超时与重试在架构设计中,往往很容易被忽略,及配置的合理性,另外如想要很好的治理,并非是容易的,复杂度和成本都很高,对我们基础组件的标准化和基础设施要求很高,只有基础组件的标准化之后,才能够进行治理,再结合配置中心,对各个组件进行配置下发,其组件包括缓存、RPC、消息队列等;例如超时是通过调用链来进行治理的,是依赖于基础设施服务的;重试中的避免链路重试的风险,也依赖于组件标准化。
5.3容错、容灾相关
容错可以通过硬件冗余、错误检查和热交换再加上特殊的软件来实现,而容灾必须通过系统冗余、灾难检测和系统迁移等技术来实现。当设备故障不能通过容错机制解决而导致系统宕机时,这种故障的解决就属于容灾的范畴。
本文转载自jackl_都都,已获取转载授权,【点击跳转查看原文】
评论列表(1条)