你真的懂服务的容错性设计吗(1)

什么是服务容错性

我们在工作中经常会遇到系统故障,服务异常等情况,尤其是在大型分布式系统中,随着微服务的数据量不断增多,服务出现异常的概率也在不断增加,想必没有一个老铁敢保证自己开发的服务不会出现异常。既然我们无法保证服务不会出现异常,那么在系统设计的时候,就要多花一点时间,来考虑系统出现异常时,如何进行异常处理,让异常对整个系统的影响降到最低,尽量让用户无感知,这也就是本篇文章讨论的重点内容,服务的容错性设计

服务容错性策略有哪些

服务的容错性设计其实是提升服务可用性的一种手段,提升服务可用性的方案通常有两种:事前预防事后处理

事前预防:常用的事前预防手段是副本冗余机制,对副本机制不了解的小伙伴可以参考“副本机制在kafka中的实践”。很多公司的事前预防解决方案是这样的:给服务添加丰富的指标监控,如服务的负载监控,服务异常告警,同时给服务设置一些扩缩容的配置,比如cpu,内存负载超过70%时,会触发扩容操作,防止服务面临超过预期的突发请求时,导致大部分请求直至超时都无法完成处理,甚至导致服务崩溃,影响系统的可用性。
事后处理:更多的是在研究当服务出现异常时候该怎么做的问题,其目标主要是:当服务出现异常时,如何让异常的影响达到最小,如何让服务自动恢复尽量让用户无感知,这个也是服务容错性设计重点,对于常用的服务容错策略,主要有以下几种:
故障转移(Failover)

故障转移是指,如果被调用的服务器出现故障,系统不会立即向调用者返回失败结果,而是自动切换到其他服务副本,尝试其他副本能否返回成功调用的结果,从而保证了整体的高可用性。

故障转移的容错策略应该有一定的调用次数限制,比如允许最多重试三个服务,如果都发生报错,那还是会返回调用失败。引入调用次数的限制,不仅是因为重试有执行成本,更是因为过度的重试反而可能让系统处于更加不利的状况。

我们看一个例子。现在有 Service A → Service B → Service C 这么一条调用链。假设 A 的超时阈值为 100 毫秒,而 B 调用 C 需要 60 毫秒,然后不幸失败了,这时候做故障转移其实已经没有太大意义了。因为即使下一次调用能够返回正确结果,也很可能同样需要耗费 60 毫秒的时间,时间总和就已经超过了 Service A 的超时阈值。所以,在这种情况下故障转移反而对系统是不利的。

快速失败(Failfast)

有一些业务场景是不允许做故障转移的,因为故障转移策略能够实施的前提,是服务具有幂等性。那对于非幂等的服务,重复调用就可能产生脏数据,引起的麻烦远大于单纯的某次服务调用失败。这时候,就应该把快速失败作为首选的容错策略。

比如,在支付场景中,需要调用银行的扣款接口,如果该接口返回的结果是网络异常,那程序很难判断到底是扣款指令发送给银行时出现的网络异常,还是银行扣款后给服务返回结果时出现的网络异常。为了避免重复扣款,此时最恰当的方案就是尽快让服务报错并抛出异常,坚决避免重试,由调用者自行处理。

安全失败(Failsafe)

在一个调用链路中的服务,通常也有主路和旁路之分,并不见得每个服务都是不可或缺的,属于旁路逻辑的一个显著特点是,服务失败了也不影响核心业务的正确性。

比如,开发基于 Spring 管理的应用程序时,通过扩展点、事件或者 AOP 注入的逻辑往往就属于旁路逻辑,典型的有审计、日志、调试信息,等等。

属于旁路逻辑的另一个显著特征是,后续处理不会依赖其返回值,或者它的返回值是什么都不会影响后续处理的结果。比如只是将返回值记录到数据库,并不使用它参与最终结果的运算。

对这类逻辑,一种理想的容错策略是,即使旁路逻辑调用失败了,也当作正确来返回,如果需要返回值的话,系统就自动返回一个符合要求的数据类型的对应零值,然后自动记录一条服务调用出错的日志备查即可。这种容错策略,被称为安全失败。

故障恢复(Failback)

故障恢复是指,当服务调用出错了以后,将该次调用失败的信息存入一个消息队列中,然后由系统自动开始异步重试调用。

从这个定义中也可以看出,故障恢复策略尽力促使失败的调用最终能够被正常执行,故障恢复也要求服务必须具备幂等性。

由于它的重试是后台异步进行,即使最后调用成功了,原来的请求也早已经响应完毕,所以,故障恢复策略一般用于对实时性要求不高的主路逻辑,也适合处理那些不需要返回值的旁路逻辑。为了避免在内存中的异步调用任务堆积,故障恢复与故障转移一样,也应该有最大重试次数的限制。

并行调用(Forking)

并行调用策略,是指一开始就同时向多个服务副本发起调用,只要有其中任何一个返回成功,那调用便宣告成功。

这种策略是在一些关键场景中,使用更高的执行成本换取执行时间和成功概率的策略。这种处理思路,其实对应的就是,咱们在日常生活中,对一些重要环节采取的“双重保险”或者“多重保险”的处理思路。

以上这些容错策略,可以指导我们更好的进行服务容错设计,在下一篇文章中,我们一起学习一下如何使用上面这些容错策略,来帮助我们在业务开发中进行服务容错性设计,以及常用的服务容错设计模式。

原文始发于微信公众号(小李哥编程):你真的懂服务的容错性设计吗(1)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/95716.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!