IHttpClientFactory 및 Polly 정책을 통해 HTTP 호출 재시도 가능하도록 하는 방법입니다.
즉, API 호출 시 응답이 없거나 정상적인 응답을 받지 못한 경우 재호출하는 기능을 말합니다.
이 기능은 Polly 를 이용하면 쉽게 구현이 가능합니다.
ASP.NET Core 웹앱 프로젝트 생성
Program.cs 에 아래 코드 추가
AddHttpClient 하는 부분에 AddPolicyHandler를 통해 정책을 추가합니다.
builder.Services.AddHttpClient("apiClient", client =>
{
client.BaseAddress = new Uri("https://localhost:7018/WeatherForecast/");
}
// Polly 정책 추가
).AddPolicyHandler(Policy.HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode).RetryAsync(3));
위 내용은 api 응답이 성공이 아닌 경우 3번 재시도를 한다는 뜻입니다.
즉, 처음 호출을 제외하고 3번이므로 총 4번을 호출게 되는 것입니다.
코드 단에서 위에서 선언된 해당 Client 를 가져와 쓸 때는 기존과 동일한 방식으로 사용하면 됩니다.
<Index.cshtml.cs>
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace WebApp.PollyTest.Pages
{
public class IndexModel : PageModel
{
private readonly ILogger<IndexModel> logger;
private readonly IHttpClientFactory factory;
public IndexModel(ILogger<IndexModel> logger, IHttpClientFactory factory)
{
this.logger = logger;
this.factory = factory;
}
public async void OnGet()
{
// 선언된 Client 가져오기
var client = factory.CreateClient("apiClient");
// API 호출
var result = await client.GetAsync("GetWeatherForecastData");
if (result.IsSuccessStatusCode)
{
var data = await result.Content.ReadAsStringAsync();
}
}
}
}
API 를 호출하여 정상응답을 못 받은 경우 3번 추가로 시도되면 정상입니다.
위 동작을 테스트 하기 위해 API 서버를 구성해 봤습니다.
ASP.NET Core 웹 API 프로젝트를 생성합니다.
api는 기존에 디펄트로 만들어진 날씨예보 API를 사용했고 static 필드로 testIndex를 두어
3번째 시도까지는 BadRequest를 전달하고 4번째 시도 시 정상결과를 반환하도록 했습니다.
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
namespace WebApp.APITest.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
public static int testIndex = 0;
private static readonly string[] Summaries = new[]
{"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet]
[Route("GetWeatherForecastData")]
public ActionResult<WeatherForecast> GetWeatherForecastData()
{
// 3번시도 까지는 BadRequest
if (testIndex < 3)
{
testIndex++;
Debug.WriteLine($"★ {testIndex} BadRequest");
return BadRequest();
}
else
{
// 4번째 결과 정상 처리
Debug.WriteLine($"★ {testIndex} Sucess!!");
return Ok(new WeatherForecast
{
Date = DateTime.Now.AddDays(1),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
});
}
}
}
}
Server(WebApp.APITest)를 실행하고 Client(WebApp.PollyTest)를 실행하면 아래처럼 시도를 3번 하고 4번째에서 결과를 얻어 Client에서는 정상으로 반환되는 것을 확인할 수 있습니다.
★ 1 BadRequest
System.Net.Http.HttpClient.apiClient.ClientHandler: Information: Received HTTP response headers after 67.6567ms - 400
System.Net.Http.HttpClient.apiClient.ClientHandler: Information: Sending HTTP request GET https://localhost:7018/WeatherForecast/GetWeatherForecastData
★ 2 BadRequest
System.Net.Http.HttpClient.apiClient.ClientHandler: Information: Received HTTP response headers after 2.0198ms - 400
System.Net.Http.HttpClient.apiClient.ClientHandler: Information: Sending HTTP request GET https://localhost:7018/WeatherForecast/GetWeatherForecastData
★ 3 BadRequest
System.Net.Http.HttpClient.apiClient.ClientHandler: Information: Received HTTP response headers after 1.3116ms - 400
System.Net.Http.HttpClient.apiClient.ClientHandler: Information: Sending HTTP request GET https://localhost:7018/WeatherForecast/GetWeatherForecastData
★ 3 Sucess!!
System.Net.Http.HttpClient.apiClient.ClientHandler: Information: Received HTTP response headers after 3.6078ms - 200
System.Net.Http.HttpClient.apiClient.LogicalHandler: Information: End processing HTTP request after 104.5019ms - 200
Client Result Sucess!!
[Source]
https://github.com/kei-soft/WebApp.PollyTest
C# flac 파일에서 음악 정보 가져오기 - TagLibSharp (0) | 2024.06.09 |
---|---|
Selenium 사용하여 웹사이트 열기 (0) | 2024.06.04 |
SocketsHttpHandler 사용 시 SSL 무시하기 (0) | 2024.06.04 |
HttpClientHandler 사용 시 SSL 무시하기 (0) | 2024.06.04 |
C# Reflection 을 이용해 특정 Property 들만 Select 하기 (0) | 2024.05.14 |