基于ASP.NET CORE 6 使用Polly来实现处理Http请求异常

一、简介

Polly 是一个 .NET 弹性和瞬态故障处理库,旨在帮助开发者构建更健壮和可靠的应用程序。它提供了一系列策略,如重试、断路器、超时、回退和隔离等,用于处理瞬态故障和提高系统的弹性。

二、原理和功能

Polly 的核心原理是通过定义和应用策略来处理可能出现的故障。这些策略可以组合使用,以应对不同类型的故障场景。以下是一些主要功能:

  1. 重试(Retry):在操作失败时自动重试指定次数。
  2. 断路器(Circuit Breaker):在检测到连续失败后短暂停止操作,以防止系统过载。
  3. 超时(Timeout):为操作设置最大执行时间,超过时间则取消操作。
  4. 回退(Fallback):在操作失败时提供备用方案。
  5. 隔离(Bulkhead Isolation):限制并发执行的操作数量,以防止资源耗尽。

三、作用

Polly 的主要作用是增强应用程序的弹性和容错能力,使其能够更好地应对网络抖动、服务不可用等瞬态故障,从而提高系统的稳定性和用户体验。

四、实现案例

以下是基于 ASP.NET Core 6 和 Polly 的几个实际应用场景的代码示例。

场景一:重试策略

在这个示例中,我们将使用 Polly 的重试策略来处理 HTTP 请求失败的情况。

using Microsoft.Extensions.DependencyInjection;
using Polly;
using Polly.Extensions.Http;
using System;
using System.Net.Http;
using System.Threading.Tasks;

var builder = WebApplication.CreateBuilder(args);

// 注册 HttpClient 并配置重试策略
builder.Services.AddHttpClient("MyClient")
    .AddPolicyHandler(GetRetryPolicy());

var app = builder.Build();

app.MapGet("/", async (IHttpClientFactory httpClientFactory) =>
{
    var client = httpClientFactory.CreateClient("MyClient");
    var response = await client.GetAsync("https://api.example.com/data");
    return response.IsSuccessStatusCode ? "Success" : "Failed";
});

app.Run();

static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
    return HttpPolicyExtensions
        .HandleTransientHttpError()
        .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
}
场景二:断路器策略

在这个示例中,我们将使用 Polly 的断路器策略来保护系统免受连续失败的影响。

using Microsoft.Extensions.DependencyInjection;
using Polly;
using Polly.CircuitBreaker;
using Polly.Extensions.Http;
using System;
using System.Net.Http;
using System.Threading.Tasks;

var builder = WebApplication.CreateBuilder(args);

// 注册 HttpClient 并配置断路器策略
builder.Services.AddHttpClient("MyClient")
    .AddPolicyHandler(GetCircuitBreakerPolicy());

var app = builder.Build();

app.MapGet("/", async (IHttpClientFactory httpClientFactory) =>
{
    var client = httpClientFactory.CreateClient("MyClient");
    try
    {
        var response = await client.GetAsync("https://api.example.com/data");
        return response.IsSuccessStatusCode ? "Success" : "Failed";
    }
    catch (BrokenCircuitException)
    {
        return "Circuit is open!";
    }
});

app.Run();

static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
{
    return HttpPolicyExtensions
        .HandleTransientHttpError()
        .CircuitBreakerAsync(2, TimeSpan.FromMinutes(1));
}
场景三:超时策略

在这个示例中,我们将使用 Polly 的超时策略来确保 HTTP 请求不会无限期挂起。

using Microsoft.Extensions.DependencyInjection;
using Polly;
using Polly.Timeout;
using Polly.Extensions.Http;
using System;
using System.Net.Http;
using System.Threading.Tasks;

var builder = WebApplication.CreateBuilder(args);

// 注册 HttpClient 并配置超时策略
builder.Services.AddHttpClient("MyClient")
    .AddPolicyHandler(GetTimeoutPolicy());

var app = builder.Build();

app.MapGet("/", async (IHttpClientFactory httpClientFactory) =>
{
    var client = httpClientFactory.CreateClient("MyClient");
    try
    {
        var response = await client.GetAsync("https://api.example.com/data");
        return response.IsSuccessStatusCode ? "Success" : "Failed";
    }
    catch (TimeoutRejectedException)
    {
        return "Request timed out!";
    }
});

app.Run();

static IAsyncPolicy<HttpResponseMessage> GetTimeoutPolicy()
{
    return Policy.TimeoutAsync<HttpResponseMessage>(10); // 10秒超时
}
场景四:组合策略

在这个示例中,我们将组合重试、断路器和超时策略,以应对复杂的故障场景。

using Microsoft.Extensions.DependencyInjection;
using Polly;
using Polly.CircuitBreaker;
using Polly.Extensions.Http;
using Polly.Timeout;
using System;
using System.Net.Http;
using System.Threading.Tasks;

var builder = WebApplication.CreateBuilder(args);

// 注册 HttpClient 并配置组合策略
builder.Services.AddHttpClient("MyClient")
    .AddPolicyHandler(GetCombinedPolicy());

var app = builder.Build();

app.MapGet("/", async (IHttpClientFactory httpClientFactory) =>
{
    var client = httpClientFactory.CreateClient("MyClient");
    try
    {
        var response = await client.GetAsync("https://api.example.com/data");
        return response.IsSuccessStatusCode ? "Success" : "Failed";
    }
    catch (BrokenCircuitException)
    {
        return "Circuit is open!";
    }
    catch (TimeoutRejectedException)
    {
        return "Request timed out!";
    }
});

app.Run();

static IAsyncPolicy<HttpResponseMessage> GetCombinedPolicy()
{
    var retryPolicy = HttpPolicyExtensions
        .HandleTransientHttpError()
        .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));

    var circuitBreakerPolicy = HttpPolicyExtensions
        .HandleTransientHttpError()
        .CircuitBreakerAsync(2, TimeSpan.FromMinutes(1));

    var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(10);

    return Policy.WrapAsync(retryPolicy, circuitBreakerPolicy, timeoutPolicy);
}
方法参数解释:
return HttpPolicyExtensions 
.HandleTransientHttpError() 
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound) .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));

具体来说,这段代码的作用是:

  1. 处理瞬态 HTTP 错误(如网络问题、服务器过载等)。
  2. 如果收到 404 Not Found 响应,也会进行重试。
  3. 重试三次,每次重试之间的等待时间呈指数增长。

下面是对每个方法的详细解释:

  1. HttpPolicyExtensions.HandleTransientHttpError()

    • 这是一个扩展方法,用于捕获常见的瞬态 HTTP 错误,如 5xx 系列的服务器错误和网络连接失败等。
  2. .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)

    • 这个方法用于指定额外的条件,即当 HTTP 响应状态码为 404 Not Found 时也进行重试。
  3. .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)))

    • WaitAndRetryAsync 方法定义了一个异步的重试策略。
    • 参数 3 表示最多重试三次。
    • 第二个参数是一个函数,定义了每次重试之间的等待时间。这里使用的是指数退避算法:第一次重试等待 2^1 秒,第二次重试等待 2^2 秒,第三次重试等待 2^3 秒。

五、总结:

        通过这些示例,你可以看到如何使用 Polly 来增强 ASP.NET Core 应用程序的弹性和容错能力。根据具体的业务需求,可以灵活组合和调整这些策略。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值