基于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 应用程序的弹性和容错能力。根据具体的业务需求,可以灵活组合和调整这些策略。

<think>好的,我现在需要帮助用户了解在ASP.NET中发起HTTP请求的可用方法。根据用户之前的问题,他们提到了加密的jquery.aspx解密,现在转向了ASP.NET中的HTTP请求方法。我需要结合之前的对话和用户提供的三个引用来组织答案。 首先,用户的问题是关于ASP.NET发起HTTP请求的方法列表。他们可能希望得到一个全面的方法概述,包括不同的类和策略。之前的回答中,用户提到了HttpClient、HttpWebRequest、WebClient,以及Polly的重试策略。现在需要整合这些信息,同时参考用户提供的三个引用。 引用1提到了HttpClient和构造带参数的请求,引用2是关于Polly异常处理策略,引用3是HttpClient的使用示例。需要将这些内容融入回答中,确保涵盖不同方法,同时注意用户可能需要实际代码示例和最佳实践。 我需要先列出ASP.NET中发起HTTP请求的主要方法,包括HttpClient、HttpWebRequest、WebClient,以及RestSharp和Polly的组合使用。每个方法需要简要说明,优缺点,并提供代码示例,特别是用户提到的引用中的例子。例如,引用3中的HttpClient示例可以直接使用,引用2中的Polly策略可以结合到HttpClient部分,说明如何增强可靠性。 此外,用户可能关心如何传递参数,比如查询参数或请求体,这在引用1中提到,需要在HttpClient部分详细说明。同时,注意用户之前的问题涉及加密和解密,虽然现在的问题不同,但可能需要确保回答的代码示例符合安全实践,比如使用HTTPS和正确处理敏感数据。 最后,要生成相关问题,帮助用户深入理解,比如比较不同方法、处理异常、参数传递方式等。确保结构清晰,分点列出,代码示例正确,并引用提供的引用标记。 需要注意,用户可能混淆了ASP.NET的不同版本(如Web Forms和Core),所以需要明确区分,并在适用时指出版本差异。例如,HttpWebRequest和WebClient在较新的Core版本中可能不推荐使用,而HttpClient是推荐方式。同时,PollyCore中的集成可能更常见,需要提及。 总结步骤:1. 列出主要方法;2. 每个方法的说明、代码示例、优缺点;3. 结合Polly的重试策略;4. 参数处理;5. 注意事项;6. 相关问题。</think>#### ASP.NET 中发起 HTTP 请求的常用方法列表 以下是 ASP.NET 中发起 HTTP 请求的核心方法,结合代码示例和适用场景进行说明: --- ### 1. **`HttpClient`(推荐方式)** **适用场景**:现代 ASP.NET(包括 Core 和 Framework 4.5+)中异步请求、长连接复用、复杂参数传递。 **特点**: - 支持异步/同步请求 - 内置连接池管理,避免端口耗尽问题 - 可扩展性强(如结合 `Polly` 实现重试策略[^2]) **示例代码(带参数请求)**: ```csharp using System; using System.Net.Http; using System.Threading.Tasks; public class HttpClientDemo { private static readonly HttpClient _client = new HttpClient(); public static async Task GetWithQueryParamsAsync() { // 构造带查询参数的 URL var baseUrl = "https://api.example.com/search"; var queryParams = new System.Collections.Specialized.NameValueCollection { { "keyword", "ASP.NET" }, { "page", "1" } }; var fullUrl = $"{baseUrl}?{queryParams}"; // 发起 GET 请求 HttpResponseMessage response = await _client.GetAsync(fullUrl); response.EnsureSuccessStatusCode(); string content = await response.Content.ReadAsStringAsync(); Console.WriteLine(content); } public static async Task PostWithJsonBodyAsync() { // POST JSON 数据 var payload = new { UserId = 1001, Action = "subscribe" }; var jsonContent = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(payload), Encoding.UTF8, "application/json"); HttpResponseMessage response = await _client.PostAsync("https://api.example.com/events", jsonContent); } } ``` **优点**:线程安全、性能优化、支持流式处理 **缺点**:需注意单例生命周期管理(避免频繁实例化)[^3] --- ### 2. **`HttpWebRequest`(传统方式)** **适用场景**:低版本 .NET Framework(<4.5)或需要细粒度控制请求头/流。 **特点**: - 完全控制请求细节(如超时、协议版本) - 同步/异步均可实现 **示例代码**: ```csharp var request = (HttpWebRequest)WebRequest.Create("https://api.example.com/data"); request.Method = "GET"; request.Timeout = 3000; using (var response = (HttpWebResponse)request.GetResponse()) using (var stream = response.GetResponseStream()) using (var reader = new StreamReader(stream)) { Console.WriteLine(reader.ReadToEnd()); } ``` **优点**:兼容性强 **缺点**:代码冗余、需手动处理连接复用 --- ### 3. **`WebClient`(简化操作)** **适用场景**:快速实现简单下载/上传操作。 **特点**: - 同步方法为主(如 `DownloadString`) - 支持 `WebRequest` 的封装 **示例代码**: ```csharp using (var client = new WebClient()) { client.QueryString.Add("category", "books"); // 添加查询参数 string result = client.DownloadString("https://api.example.com/items"); } ``` **优点**:代码简洁 **缺点**:不支持异步流、性能较差(频繁创建实例) --- ### 4. **第三方库(如 `RestSharp`)** **适用场景**:需要更友好的 API 设计或复杂 REST 交互。 **特点**: - 链式调用语法 - 自动序列化/反序列化 **示例代码**: ```csharp var client = new RestClient("https://api.example.com"); var request = new RestRequest("users/{id}", Method.Get); request.AddUrlSegment("id", "1001"); // 路径参数 request.AddQueryParameter("active", "true"); // 查询参数 var response = client.Execute(request); Console.WriteLine(response.Content); ``` --- ### 5. **结合 Polly 的增强策略[^2]** 通过 `HttpClient` + `Polly` 实现自动重试、熔断等机制: ```csharp using Polly; using Polly.Retry; var retryPolicy = Policy .Handle<HttpRequestException>() .OrResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode) .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); await retryPolicy.ExecuteAsync(async () => { var response = await _client.GetAsync("https://api.example.com/unstable-endpoint"); response.EnsureSuccessStatusCode(); return response; }); ``` --- ### **参数传递方式对比** | 方式 | 适用方法 | 示例 | |---------------|------------------|-------------------------------| | 查询参数 | GET | `?key1=value1&key2=value2` | | 路径参数 | RESTful API | `/users/{id}` | | 请求体 (JSON) | POST/PUT/PATCH | `{ "name": "test" }` | | 表单数据 | POST (x-www-form-urlencoded) | `key1=value1&key2=value2` | --- ### **注意事项** 1. **连接管理**:`HttpClient` 应静态复用,避免 `SocketException`[^3] 2. **编码安全**:使用 `Uri.EscapeDataString` 处理特殊字符 3. **超时设置**:通过 `HttpClient.Timeout` 或 `CancellationToken` 控制 4. **HTTPS 强制**:生产环境务必使用 `https://` 协议 --- #### 相关问题 1. 如何通过 `HttpClient` 实现文件上传? 2. `HttpClient` 和 `HttpWebRequest` 的性能差异有多大? 3. 如何在 ASP.NET Core 中配置 HTTP 请求的全局超时? 4. 使用 `Polly` 时如何避免重试风暴?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值