当我知道代码因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。请帮忙。
答案 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策略最终仍会重新抛出WebException
:this 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; }