美文网首页
设计可靠通信之如何优雅重试

设计可靠通信之如何优雅重试

作者: robot_test_boy | 来源:发表于2022-08-27 00:17 被阅读0次

多个服务相互依赖最终才能完成应用中最有价值的功能。一个微服务出现故障,会对协作方以及应用的最终用户产生怎样的影响呢?

如果故障是不可避免的,那么在设计和开发服务时,要尽可能地提高服务的可用性和运行的正确性以及在发生故障以后快速恢复的能力。这对于实现服务的可恢复性是至关重要的。以确保在协作方服务不可用时服务依旧能够最大限度地正确运行有几种方式,重试;后备方案(fallback)、缓存和优雅降级;超时和最后期限;熔断器;通信代理(communication broker)

本文先先看重试,如何优雅的重试?

设想一下,holding服务发出获取价格的请求失败了,请求返回了一个错误信息。那么,这次失败是重复发一下请求就可能会成功的孤立的失败事件,还是下次调用仍有极大可能同样失败的系统性故障呢?从服务调用方的角度来讲,这是无法判断的。我们期望获取数据的调用是幂等的(idempotent),就是对目标系统的状态没有影响,并且是可以重复的

故障可能是孤立的也可能是持续性的,但是holding服务并不能通过一次调用就知道是哪种情况。

如果故障是孤立和暂时性的,那么重试是一个很合理的选择。当异常行为发生时,重试操作一方面能够减轻对终端用户的影响,另一方面还能减少运维工作人员的介入。为重试方案做好规划是很重要的:每次重试要花费几十毫秒时间,所以服务消费方只能在超过合理的响应时间之前进行一定次数的重试。

如果故障是持续性的且market-data服务的承载力下降了,后续的请求会使这一问题进一步恶化并导致系统稳定性下降。假设每次请求market-data服务失败后都重试5次,那么每个失败请求都会导致5个新的请求;重试的请求量会持续增长。随着market-data服务要处理的重试请求越来越多,它越来越没有资源处理其他正常请求。最坏的情况是,最初的故障不断被放大,market-data服务活活被重试方案压死了

如果发生持续性故障,面对断断续续的失败情况,该如何在不扩大系统故障范围的前提下通过重试技术来提高服务的可恢复性呢?

首先,可以在这些重试操作之间使用一个变化的时间间隔来保证这些请求分布更加均匀,降低重试的那部分请求负载的频率。这就是指数退避(exponential back-off)策略,它的目的是给系统提供一个较低负载的时间,以便于恢复正常

很遗憾,指数退避会引发另一种新的古怪行为。设想一下,短时的故障阻断了一些对market-data服务的调用,进而触发重试。指数退避算法会让服务将这些重试请求放到一起安排调度,这会进一步强化重试调用对服务的影响,就像往池塘扔石头激起的涟漪。

作为替代,指数退避应该包含一个随机元素——抖动(jitter)将重试分散到一个更恒定的速率,避免过多的大量重试同时执行。

这一策略能够确保在有多个客户端等待重试时,这些客户端不大会同时发起重试操作。

为了容忍间歇性的依赖型错误,重试是一种有效的策略。但是,在使用过程中,我们需要格外小心,以免导致底层问题进一步恶化或耗费不必要的资源:永远要限制重试的总次数使用带抖动的指数退避策略来均匀地分配重试请求和避免进一步加剧负载仔细考虑哪些错误情况应该触发重试,以及哪些重试不大可能成功、哪些重试永远不会成功。

当服务达到了重试次数的上限或者不能对请求发起重试时,开发者可以接纳这个失败结果或者找个其他的办法来继续处理这个请求。

摘取自 摩根·布鲁斯和保罗·A.佩雷拉的《微服务实战》

相关文章

网友评论

      本文标题:设计可靠通信之如何优雅重试

      本文链接:https://www.haomeiwen.com/subject/mpvogrtx.html