繁体   English   中英

用于工作流的 C# 中的 Polly 模式?

[英]Polly patterns in C# for a workflow?

我有一个这样的工作流程:

  • 调用 API 方法
    • 如果抛出任何异常但超时,程序会记录该异常并抛出它。
  • 如果抛出超时,程序必须调用另一个 API 方法。
    • 调用另一个 API 方法后,如果一切正常,程序将返回结果。
    • 否则程序会抛出异常并记录下来。

两种 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?

如果我正确理解您的工作流程,那么您根本不需要重试策略。 回退策略就足够了。

所以,假设CallApiCallAnotherApi是这样实现的:

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将始终因请求超时而失败
  • 由于调用了Ensure方法, CallAnotherApi将始终抛出HttpRequestException

现在让我们看看策略定义和用法:

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 时才应触发回退策略
  • 如果CallApiCallAnotherApi抛出异常,则ExecuteAsync将抛出异常

让我们一一看看不同的场景

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;崩溃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;崩溃throw;

在这种情况下,polly 回退就足够了。 像这样....

var fallbackPolicy = Policy<HttpResponseMessage>
.Handle<Exception>()
.FallbackAsync((r, c, ct) => throw r.Exception,
async (r, c) =>
{
    Log(r.Message);
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM