制定政策

时间:2018-12-14 23:41:13

标签: c# api polly

当我知道代码因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。请帮忙。

2 个答案:

答案 0 :(得分: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子句捕获异常并且不将其抛出时,catch块完成时,该异常不会传播到catch块之外。 catch块将吞下该异常。

为使Polly处理异常,需要将该异常从传递给policy.Execute(() => )的委托中传播出去,以便将其重新引发给策略,然后由该策略进行处理。


编辑:上面的答案有意演示了从发布的代码中进行更改以使Polly策略处理异常的最低要求。正如Cyrus在评论中所建议的那样,如果仅将try / catch用于某些额外的日志记录,则可以在Polly策略的onRetry子句中这样做,然后删除try / catch


第二编辑:如果担心的是,如果所有重试均失败,则Polly策略最终仍会重新抛出WebExceptionthis is intentional; RetryPolicy通过抛出最终异常来发出所有重试均未成功的信号。

如果您希望捕获最后的异常而不必进一步添加自己的try / catch,则可以使用Polly .ExecuteAndCapture(...)

答案 1 :(得分: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;
                 }