重试间隔时间:定义每次重试之间的时间间隔。
builder.Services.AddSwaggerGen(); builder.Services.AddControllers(); var app = builder.Build(); app.MapControllers();然后创建一个 ResponseController.cs 文件,添加如下操作方法:
[Route("api/[Controller]")] [ApiController] public class ResponseController : ControllerBase { [HttpGet] [Route("{id:int}")] public ActionResult GetAResponse(int id) { Random rnd = new Random(); var rndInteger = rnd.Next(1, 101); if (rndInteger >= id) { Console.WriteLine("Failure - Generate an Internal Error"); return StatusCode(StatusCodes.Status500InternalServerError); } Console.WriteLine("Failure - Generated a Success"); return Ok("Success"); } }在上述代码中,我们使用 Random 函数实现了服务内的瞬态故障。当随机生成的整数小于输入的 ID 时,有可能返回内部服务器错误。运行代码并通过 Postman 测试。根据生成的随机整数,响应服务的状态码会随机返回 200 或 500。
namespace RequestService.Controllers { [ApiController] [Route("api/[Controller]")] public class RequestController: ControllerBase { public RequestController() { // 堆代码 duidaima.com } [HttpGet] public async Task<ActionResult> MakeRequest() { var client = new HttpClient(); var response = await client.GetAsync("http://localhost:5202/api/response/25"); var response = await _clientPolicy.LinearHttpRetry.ExecuteAsync( () => client.GetAsync("http://localhost:5202/api/response/25") ); if(response.IsSuccessStatusCode) { Console.WriteLine("--> Response Service Retuned Success"); return Ok(); } Console.WriteLine("--> Response Service Retuned Failure"); return StatusCode(StatusCodes.Status500InternalServerError); } } }可以运行请求服务并在 Postman 中验证。此时我们会从响应服务中得到失败消息,因为还未实现重试机制。
dotnet add package Microsoft.Extensions.Http.Polly创建一个名为 Policies 的文件夹,并添加 ClientPolicy 类文件,代码如下:
using Polly; using Polly.Retry; namespace RequestService.Policies { public class ClientPolicy { public AsyncRetryPolicy<HttpResponseMessage> ImmediateHttpRetry {get;} public AsyncRetryPolicy<HttpResponseMessage> LinearHttpRetry {get;} public AsyncRetryPolicy<HttpResponseMessage> ExponentialHttpRetry {get;} public ClientPolicy() { ImmediateHttpRetry = Policy.HandleResult<HttpResponseMessage> ( res => !res.IsSuccessStatusCode).RetryAsync(5); LinearHttpRetry = Policy.HandleResult<HttpResponseMessage> ( res => !res.IsSuccessStatusCode). WaitAndRetryAsync(5, retryAttempt => TimeSpan.FromSeconds(3)); ExponentialHttpRetry = Policy.HandleResult<HttpResponseMessage> ( res => !res.IsSuccessStatusCode). WaitAndRetryAsync(5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2,retryAttempt))); } } }在上述代码中,我们在构造函数中初始化了不同的重试策略。以 LinearHttpRetry 为例,若返回结果不是 SuccessStatusCode,则 WaitAndRetryAsync 方法会重试 5 次,每次间隔 3 秒。接着,我们在 Program.cs 中通过依赖注入配置 ClientPolicy:
builder.Services.AddSingleton<ClientPolicy> (new ClientPolicy());然后在 RequestController 中使用 ClientPolicy:
private readonly ClientPolicy _clientPolicy; private readonly IHttpClientFactory _clientFactory; public RequestController(ClientPolicy clientPolicy, IHttpClientFactory clientFactory) { _clientPolicy = clientPolicy; _clientFactory = clientFactory; } [HttpGet] public async Task<ActionResult> MakeRequestNormalHttpClient() { var client = new HttpClient(); var response = await _clientPolicy.LinearHttpRetry.ExecuteAsync(() => client.GetAsync("http://localhost:5202/api/response/25") ); if(response.IsSuccessStatusCode) { Console.WriteLine("--> Response Service Retuned Success"); return Ok(); } Console.WriteLine("--> Response Service Retuned Failure"); return StatusCode(StatusCodes.Status500InternalServerError); }为了更好地管理策略,可以在 Program.cs 中为命名的 HttpClient 添加策略:
builder.Services.AddHttpClient("Test") .AddPolicyHandler(request => request.Method == HttpMethod.Get ? new ClientPolicy().LinearHttpRetry : new ClientPolicy().LinearHttpRetry );在控制器中使用命名的 HttpClient:
public async Task<ActionResult> MakeRequest() { var client = _clientFactory.CreateClient("Test"); var response = await client.GetAsync("http://localhost:5202/api/response/25"); if (response.IsSuccessStatusCode) { Console.WriteLine("--> Response Service Returned Success"); return Ok(); } Console.WriteLine("--> Response Service Returned Failure"); return StatusCode(StatusCodes.Status500InternalServerError); }由于我们在 Program.cs 中为命名的 Http 客户端配置了策略,因此可以直接使用 IHttpClientFactory 来创建客户端,并且策略已经启用。让我们运行代码并在 Postman 中测试 LinearHttpRetry 策略。在 Postman 中,我们成功地测试了线性等待策略。