Refit ApiException的最佳重试策略是什么?

4

我正在使用RefitPolly来调用restful API,并且我想知道Refits ApiException的重试(如果有的话)策略应该是什么?

public static PolicyWrap MyRetryPolicy()
{
        // Try few times with little more time between... maybe the 
        // connection issue gets resolved
        var wireServerNetworkIssue = Policy.Handle<WebException>() 
                                    .WaitAndRetryAsync(new[] {
                                    TimeSpan.FromSeconds(1),
                                    TimeSpan.FromSeconds(2),
                                    TimeSpan.FromSeconds(4)});
        var policyList = new List<Policy>();

        // But if there is something wrong with the api
        // I should do what (if general)?
        var api = Policy.Handle<ApiException>()
                  .RetryAsync(1, onRetry: async (exception, i) =>
                  {
                       await Task.Run(() =>
                       {
                           // What would be normal to do here?
                           // Try again or do some circuit braking?
                       });
                  });

        policyList.Add(wireServerNetworkIssue);
        policyList.Add(api);

        return Policy.Wrap(policyList.ToArray());
}

然后我像这样使用它。
try
{
    myApi = RestService.For<MyApi>("api base url");
    var policyWrapper = Policies.Policies.MyRetryPolicyWrapper();
    var response  = await policy.ExecuteAsync(() => myApi.SendReceiptAsync(receipt));
}
catch (ApiException apiEx)
{
  //Do something if the retry policy did´t fix it.
}
catch (WebException webEx)
{
  //Do something if the retry policy did´t fix it.
}

问题

针对 ApiExceptions,什么是正常的重试策略?您只是进行断路器处理,还是在什么情况下会采取措施进行恢复?

答案可能是“取决于您的服务返回什么”,但我必须问一下。


在您原来的问题的onRetry委托中,您不应该需要使用await Task.Run(() => { } );(除非您有意要在后台线程上运行onRetry操作)。只需在委托内部使用await即可使委托具有基于任务的返回类型。此外,如果您希望onretry操作异步运行,请使用Polly的.RetryAsync(...)重载,其中包含onRetryAsync参数,而不是onRetry - mountain traveller
1个回答

2
如果返回的 ApiException 包含有意义的 HttpStatusCode StatusCode 属性,你可以选择哪些状态码值值得重试;Polly readme 中建议如下:
int[] httpStatusCodesWorthRetrying = {408, 500, 502, 503, 504}; 

针对特定于所调用API的ApiException,只有了解这些特定于API的错误代表什么,才能指导是否重试它们。
如果您选择在某种类型的异常过多时进行熔断,则应将熔断器包装到您的 PolicyWrap 中,而不是在重试策略的 onRetry 委托中执行。Polly在这里讨论了“为什么要熔断?”,并在自述文件熔断器部分底部链接到了一些其他熔断器博客文章。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接