问题描述
两种 API 方法具有相同类型的结果。 我想通过波利政策来实现这一点。
这是我的示例代码:
var retryPolicy = Policy
.Handle<HttpRequestException>(ex => ex.StatusCode == HttpStatusCode.RequestTimeout)
.RetryAsync(1,async (exception,retryCount) =>
await CallAnotherAPI());
var fallbackPolicy = Policy<HttpResponseMessage>
.Handle<Exception>()
.FallbackAsync((r,c,ct) => throw r.Exception,async (r,c) =>
{
Log(r.Message);
});
var result = await fallbackPolicy
.WrapAsync(retryPolicy)
.ExecuteAsync(async () =>
{
await CallAPI();
});
但它不起作用并且一直执行 fallbackPolicy。如何编写如果 retryPolicy 为真,则不会执行 fallbackPolicy 的代码?
解决方法
如果我正确理解您的工作流程,那么您根本不需要重试策略。回退策略就足够了。
所以,假设 CallApi
和 CallAnotherApi
是这样实现的:
private static HttpClient client = new HttpClient();
public static async Task<HttpResponseMessage> CallAPI()
{
return await client.GetAsync("http://httpstat.us//408");
}
public static async Task<HttpResponseMessage> CallAnotherAPI()
{
var response = await client.GetAsync("http://httpstat.us//500");
response.EnsureSuccessStatusCode();
return response;
}
- 我使用
httpstatus.us
来模拟某些 http 状态代码 -
CallApi
将始终因请求超时而失败 -
CallAnotherApi
将始终抛出HttpRequestException
,因为Ensure
方法调用
现在让我们看看策略定义和用法:
public static async Task Main(string[] args)
{
var fallbackPolicy = Policy<HttpResponseMessage>
.HandleResult(msg => msg.StatusCode == HttpStatusCode.RequestTimeout)
.FallbackAsync(async (_) => await CallAnotherAPI());
HttpResponseMessage result;
try
{
result = await fallbackPolicy
.ExecuteAsync(async () =>
{
return await CallAPI();
});
}
catch (Exception ex) {
Console.WriteLine(ex.Message); //TODO: replace with logging
throw;
}
Console.WriteLine(result.StatusCode);
}
- 仅当响应的状态代码为 408 时才应触发回退策略
-
ExecuteAsync
将抛出异常,如果CallApi
或CallAnotherApi
抛出
让我们一一看看不同的场景
CallApi
成功
public static async Task<HttpResponseMessage> CallAPI()
{
return await client.GetAsync("http://httpstat.us//200");
}
输出
OK
CallApi
失败
public static async Task<HttpResponseMessage> CallAPI()
{
var response = await client.GetAsync("http://httpstat.us//500");
response.EnsureSuccessStatusCode();
return response;
}
输出
Response status code does not indicate success: 500 (Internal Server Error).
然后应用程序因为throw;
CallApi
超时和 CallAnotherApi
成功
public static async Task<HttpResponseMessage> CallAPI()
{
return await client.GetAsync("http://httpstat.us//408");
}
public static async Task<HttpResponseMessage> CallAnotherAPI()
{
var response = await client.GetAsync("http://httpstat.us//200");
response.EnsureSuccessStatusCode();
return response;
}
输出
OK
CallApi
超时和 CallAnotherApi
失败
public static async Task<HttpResponseMessage> CallAPI()
{
return await client.GetAsync("http://httpstat.us//408");
}
public static async Task<HttpResponseMessage> CallAnotherAPI()
{
var response = await client.GetAsync("http://httpstat.us//500");
response.EnsureSuccessStatusCode();
return response;
}
输出
Response status code does not indicate success: 500 (Internal Server Error).
然后应用程序因为throw;