使用退避模式重试 - AWS 规范性指导

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用退避模式重试

目的

使用退避模式重试通过透明地重试因暂时错误而失败的操作来提高应用程序的稳定性。

动机

在分布式架构中,暂时性错误可能是由服务限制、网络连接暂时中断或临时服务不可用引起的。自动重试因这些暂时性错误而失败的操作可改善用户体验和应用程序弹性。但是,频繁重试可能会使网络带宽过载并导致争用。指数退避是一种通过增加指定重试次数的等待时间来重试操作的技术。

适用性

在以下情况下使用退避模式重试:

  • 您的服务经常限制请求以防止过载,从而导致429 请求过多调用过程异常。

  • 网络是分布式架构中不可见的参与者,临时的网络问题会导致故障。

  • 被调用的服务暂时不可用,导致故障。除非使用此模式引入退避超时,否则频繁重试可能会导致服务降级。

问题和注意事项

  • 同等性:如果对该方法的多次调用与对系统状态的单次调用具有相同的效果,则该操作被视为等同操作。当你使用带有退避模式的重试时,操作应该是等同的。否则,部分更新可能会破坏系统状态。

  • 网络带宽:如果过多的重试会占用网络带宽,从而导致响应时间变慢,则可能会导致服务降级。

  • 快速失败场景:对于非暂时性错误,如果可以确定故障原因,则使用断路器模式快速失效会更有效。

  • 退避率:引入指数退避可能会影响服务超时,从而延长最终用户的等待时间。

实现

高级架构

下图说明了服务 A 如何重试对服务 B 的调用,直到返回成功的响应。如果服务 B 在尝试几次后仍未返回成功的响应,则服务 A 可以停止重试并将失败信息返回给其调用者。

使用退避模式进行重试的高级架构

使用实现AWS服务

下图显示了客户支持平台上的票证处理工作流程。通过自动提升门票优先级,可以加快来自不满意客户的门票。该Ticket infoLambda 函数提取票证详细信息并调用Get sentimentLambda 函数。该Get sentimentLambda 函数通过将描述传递给来检查客户的情绪亚马逊理解(未显示)。

如果打电话给Get sentimentLambda 函数失败,工作流程重试该操作三次。AWS Step Functions允许您配置退避值,从而允许指数退避。

在此示例中,最多配置了三次重试,增加倍数为 1.5 秒。如果第一次重试在 3 秒后发生,则第二次重试发生在 3 x 1.5 秒 = 4.5 秒之后,第三次重试发生在 4.5 x 1.5 秒 = 6.75 秒之后。如果第三次重试不成功,工作流程将失败。退避逻辑不需要任何自定义代码——它由以下人员作为配置提供AWS Step Functions。

使用退避模式重试AWS服务

示例代码

以下代码显示了使用退避模式重试的实现。

public async Task DoRetriesWithBackOff() { int retries = 0; bool retry; do { //Sample object for sending parameters var parameterObj = new InputParameter { SimulateTimeout = "false" }; var content = new StringContent(JsonConvert.SerializeObject(parameterObj), System.Text.Encoding.UTF8, "application/json"); var waitInMilliseconds = Convert.ToInt32((Math.Pow(2, retries) - 1) * 100); System.Threading.Thread.Sleep(waitInMilliseconds); var response = await _client.PostAsync(_baseURL, content); switch (response.StatusCode) { //Success case HttpStatusCode.OK: retry = false; Console.WriteLine(response.Content.ReadAsStringAsync().Result); break; //Throttling, timeouts case HttpStatusCode.TooManyRequests: case HttpStatusCode.GatewayTimeout: retry = true; break; //Some other error occured, so stop calling the API default: retry = false; break; } retries++; } while (retry && retries < MAX_RETRIES); }

GitHub知识库

有关此模式示例架构的完整实现,请参见GitHub存储库位于https://github.com/aws-samples/retry-with-backoff

相关内容