我们调用的每个远程服务最终都会失败。无论它们多么可靠,这都是不可避免的。这些失败可能来自多种因素。网络问题,硬件问题,暂时不可用的服务,超出响应时间等。其中一些故障可能已经在短时间内自动解决,如果再次调用远程服务,它将立即成功响应。我们称这些错误为暂时错误。当我们遇到暂时性错误时,我们可以做一些事情。
最简单的选择是记录错误并放弃。由于重试时最有可能解决暂时性错误,因此您可能会猜测这不是最明智的选择。因此,正确的策略是重试失败的操作。在没有明确策略的情况下重试失败的操作很可能会给远程服务造成额外的负担,因此可能会使情况变得最糟。
应用重试策略之前应回答的一些问题是:
客户将如何确定错误是否是瞬态的?
客户应多久重试一次?
客户端应重试多长时间?
客户什么时候应该放弃?
那么,什么时候重试?
您可以确定这是暂时性错误
如果远程服务返回TransientErrorException,那就很好。但是,这并不总是可能的。在这些情况下,我们需要在解释错误时保持机敏。
客户端错误:这些是由客户端本身引起的错误。例如格式错误的请求,导致冲突或执行过多的请求。在这种情况下,远程服务将返回4xx错误。处理客户端错误的唯一方法是通过人工干预来修复客户端或请求自身。没有必要重试这些请求。
服务器错误:这些是5xx错误,表明服务器端发生了问题。在这些情况下,重试通常是安全的,因为每个5xx错误都不是瞬时错误。
网络错误:这些是由于网络问题引起的错误。例如包丢失,路由器/交换机等硬件问题等。如果可以识别出这些,可以重试。
服务是幂等的
幂等意味着,在发出多个相同的请求时,其效果与发出单个请求的效果相同
根据HTTP规范的定义,GET,HEAD,PUT和DELETE是幂等操作。因此,除非远程服务所有者建议,否则可以重试这些请求。另一方面,POST和PATCH不是幂等的,如果不应用幂等,则重试是不安全的,因为它可能会引起副作用,例如多次向客户收费。
重试策略
可以用作重试机制的几种策略。选择正确的策略取决于用例。
操作失败后,我们可以立即重试。这是我们可以实施的最简单的重试策略。在第一次失败的重试操作之后,最好放弃或回退更好的策略,因为连续重试会给远程服务造成过多的负载。
操作失败后,我们可以按固定的时间间隔重试。该策略为远程服务提供了更多时间进行恢复。
这两种策略对于与用户进行交互的应用程序都非常有用,因为这些策略会重试失败的操作,如果操作失败,则很可能会放弃。因此,用户不必等待很长时间。
如果您的服务/应用程序不直接与用户交互和/或您有奢望等待更多(例如后台操作),则应尝试指数级退避。此策略基于后续重试之间的等待时间成倍增加。这是一项非常有用的技术,因为在给定的时间段内,它比以前的两种策略都给远程服务更多的时间来恢复并创建更少的负载。
那么,什么样的指数回退策略是什么样的呢?
这是一种简单的指数退避策略算法的简化伪代码:
通过增加一些抖动来分配负载
最有可能存在多个客户端实例,因此,如果这些客户端发出的所有请求都在同一时间失败,则我们不希望这些重试重叠。增加抖动将使负载分配更加均匀。使用jiter,我们的算法将是:
通过上述介绍,我们可以知道当远程服务暂时性错误,并不是所有的错误都适用重试策略,这也是分情况而定的,更多精彩内容,请继续关注中培伟业。