0

当我知道代码针对 429 问题遇到 WebException 的事实时,有人可以建议为什么我的 Policy 句柄没有处理我的 WebException 错误吗?我已经研究了一段时间,需要一些帮助。

这是我的 Polly 政策:

return Policy.Handle<WebException>()
            .WaitAndRetry(15, // We can also do this with WaitAndRetryForever... but chose WaitAndRetry this time.
            attempt => TimeSpan.FromSeconds(0.1 * Math.Pow(2, attempt)), // Back off!  2, 4, 8, 16 etc times 1/4-second
            (exception, calculatedWaitDuration) =>  // Capture some info for logging! if needed
            {
                // This is your new exception handler! 
                Debug.WriteLine("Retry count: " + retries++);
                Debug.WriteLine("Wait Duration: " + calculatedWaitDuration);
            });

我这样使用它:

 webResponseWaitRetryPolicy.Execute(() =>
        {
            // Make a request and get a response
            UriBuilder builder = new UriBuilder(options.BaseUrl);
                builder.Port = -1;
                var query = HttpUtility.ParseQueryString(builder.Query);
                /// handle parameters
                query["client_key"] = options.ClientKey;
                query["model_id"] = model;
                query["image_url"] = imageUrl;

                builder.Query = query.ToString();
                string url = builder.ToString();
                string content = string.Empty;

                Result objResult;
               HttpWebResponse response = null;


                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.AutomaticDecompression = DecompressionMethods.GZip;
                try
                {
                   response = (HttpWebResponse)request.GetResponse();
                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        using (Stream stream = response.GetResponseStream())
                        using (StreamReader reader = new StreamReader(stream))
                        {
                            content = reader.ReadToEnd();
                        }

                        objResult = JsonConvert.DeserializeObject<Result>(content);


                }
                catch(WebException ex)
                {
                    eventualFailures++; 
                    Debug.WriteLine("Failure: " + eventualFailures);


                }
            });

        return objResult;
    }

当我运行代码时,我可以看到它触发了 WebException,但没有调用 Policy。请帮忙。

4

2 回答 2

1

try {} catch {}在 Polly 策略有机会处理它们之前,您正在吞噬抛出的异常。你在哪里:

try
{
    /* snip */
}
catch(WebException ex)
{
    eventualFailures++; 
    Debug.WriteLine("Failure: " + eventualFailures);
}

利用:

try
{
    /* snip */
}
catch(WebException ex)
{
    eventualFailures++; 
    Debug.WriteLine("Failure: " + eventualFailures);
    throw;
}

说明:当catch子句捕获异常并且不重新抛出它时,catchcatch块完成时,异常不会传播到块外。该catch块吞下异常。

为了让 Polly 处理异常,需要将异常从您传递给的委托中传播出去policy.Execute(() => ),以便将其返回给策略,然后由策略处理它。


编辑:上面的答案故意演示了需要从发布的代码中更改的最小值,以使 Polly 策略处理异常。正如赛勒斯在评论中建议的那样,如果try/的唯一用途catch是进行一些额外的日志记录,您可以onRetry在 Polly 政策的条款中这样做,并完全删除try/ catch


第二次编辑:如果担心 Polly 政策最终仍会重新抛出WebException所有重试失败的情况:这是故意的;RetryPolicy 通过重新抛出最终异常表示所有重试均未成功。

如果您希望捕获最终异常而无需添加您自己的进一步try/ ,则可以使用catchPolly 。.ExecuteAndCapture(...)

于 2018-12-16T10:58:32.173 回答
0

我感谢所有帮助的人。问题是 WebException 是 429 错误。如果我不把 try catch 方法放在那里,我的代码就会崩溃。所以我最终要做的是将政策扩展一点,使其看起来像这样。

>    public static Policy<HttpWebResponse> Get429WebResponseWaitRetryPolicy()
        {
            //Retries policy
            return Policy.Handle<WebException>().OrResult<HttpWebResponse>(r => r == null)
                .WaitAndRetry(15, // We can also do this with WaitAndRetryForever... but chose WaitAndRetry this time.
                attempt => TimeSpan.FromSeconds(0.1 * Math.Pow(2, attempt)), // Back off!  2, 4, 8, 16 etc times 1/4-second
                (exception, calculatedWaitDuration) =>  // Capture some info for logging! if needed
                {
                    // This is your new exception handler! 
                    Debug.WriteLine("Retry count: " + retries++);
                    Debug.WriteLine("Wait Duration: " + calculatedWaitDuration);
                });
        }

然后我从 API WebRequest 返回响应,Polly 策略现在能够使用抛出的错误并重试。最后看起来像这样。

Debug.WriteLine("Success: " + eventualSuccesses);
                    return response;
                }
                catch(WebException ex)
                {
                    eventualFailures++; 
                    Debug.WriteLine("Failure: " + eventualFailures);
                    return response;
                 }
于 2018-12-17T14:04:24.593 回答