728x90
728x170

IHttpClientFactory 및 Polly 정책을 통해 HTTP 호출 재시도 가능하도록 하는 방법입니다.

즉, API 호출 시 응답이 없거나 정상적인 응답을 받지 못한 경우 재호출하는 기능을 말합니다.
이 기능은 Polly 를 이용하면 쉽게 구현이 가능합니다.
 
1. 'Microsoft.Extensions.Http.Polly' Nuget Package 설치

 
2. Test Client 프로젝트 생성 및 Polly 정책 코드 작성 (WebApp.PollyTest)
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번을 호출게 되는 것입니다.
 
3. 테스트 코드 작성 
코드 단에서 위에서 선언된 해당 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번 추가로 시도되면 정상입니다.
 
4. API 테스트를 위한 API 서버 구성 (WebApp.APITest)
위 동작을 테스트 하기 위해 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

GitHub - kei-soft/WebApp.PollyTest

Contribute to kei-soft/WebApp.PollyTest development by creating an account on GitHub.

github.com

 
 

728x90
그리드형
Posted by kjun
,