Microsoft MVP성태의 닷넷 이야기
.NET Framework: 2129. C# - Polly를 이용한 클라이언트 측의 요청 재시도 [링크 복사], [링크+제목 복사],
조회: 13429
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일

(시리즈 글이 2개 있습니다.)
.NET Framework: 2126. C# - 서버 측의 요청 제어 (Microsoft.AspNetCore.RateLimiting)
; https://www.sysnet.pe.kr/2/0/13362

.NET Framework: 2129. C# - Polly를 이용한 클라이언트 측의 요청 재시도
; https://www.sysnet.pe.kr/2/0/13376




C# - Polly를 이용한 클라이언트 측의 요청 재시도

지난 글에서,

C# - 서버 측의 요청 제어 (Microsoft.AspNetCore.RateLimiting)
; https://www.sysnet.pe.kr/2/0/13362

Microsoft.AspNetCore.RateLimiting을 사용해 요청 제어를 하는 방법을 설명했는데요, 이런 서비스를 이용하는 클라이언트는 반대로 제한이 걸린 서비스에 대한 호출을 재시도해야 합니다.

파이썬의 경우, 이럴 때 Tenacity, backoff 등의 패키지를 이용해 간단한 특성 처리를 할 수 있는데요,

import openai  # for OpenAI API calls
from tenacity import (
    retry,
    stop_after_attempt,
    wait_random_exponential,
)  # for exponential backoff

@retry(wait=wait_random_exponential(min=1, max=60), stop=stop_after_attempt(6))
def completion_with_backoff(**kwargs):
    return openai.Completion.create(**kwargs)

completion_with_backoff(model="text-davinci-002", prompt="Once upon a time,")

닷넷의 경우에는 Polly 라이브러리를 이용해,

Polly
; https://www.nuget.org/packages/polly/

App-vNext/Polly
; https://github.com/App-vNext/Polly#installing-via-the-net-sdk

Implement HTTP call retries with exponential backoff with IHttpClientFactory and Polly policies
; https://learn.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/implement-http-call-retries-exponential-backoff-polly

(비록 특성을 지정하는 것처럼 간단하게는 아니지만) 유사하게 구현할 수 있습니다.

예를 들어, 지수 단위로 대기 시간이 늘어나는 Polly 정책은 (문서에서 나온 것 중에서) 다음과 같이 코딩할 수 있습니다.

// Retry a specified number of times, using a function to
// calculate the duration to wait between retries based on
// the current retry attempt (allows for exponential back-off)
// In this case will wait for
//  2 ^ 1 = 2 seconds then
//  2 ^ 2 = 4 seconds then
//  2 ^ 3 = 8 seconds then
//  2 ^ 4 = 16 seconds then
//  2 ^ 5 = 32 seconds
Policy
  .Handle<SomeExceptionType>()
  .WaitAndRetry(5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));

이것을 적용해 지난 글에서 다룬 Rate Limit가 걸린 서비스를 호출하는 예제 클라이언트 코드를 다음과 같이 재작성할 수 있습니다.

using Polly;
using System.Net;

namespace ConsoleApp1;

internal class Program
{
    public const int MaxRequests = 7;
    static async Task<int> Main(string[] args)
    {
        var retryPolicy = Policy
            .HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.ServiceUnavailable)
            .RetryAsync(5, (result, retryCount, context) =>
        {
            Console.WriteLine($"Retry {retryCount} of {context.PolicyKey} at {DateTime.Now}");
            Thread.Sleep(TimeSpan.FromSeconds(Math.Pow(2, retryCount)));
        });

        var client = new HttpClient();
        var context = new Context();

        var requests = new Task<HttpResponseMessage>[MaxRequests];
        for (int i = 0; i < MaxRequests; i++)
        {
            requests[i] = retryPolicy.ExecuteAsync(async ctx =>
            {
                return await client.GetAsync("http://localhost:5203/WeatherForecast");
            }, context);
        }

        await Task.WhenAll(requests);

        for (int i = 0; i < MaxRequests; i++)
        {
            Console.WriteLine($"{i}: {requests[i].Result.StatusCode}");
        }

        return 0;
    }
}

Retry 1 of AsyncRetryPolicy`1-5df14b8b at 2023-06-01 오후 2:58:14
Retry 2 of AsyncRetryPolicy`1-5df14b8b at 2023-06-01 오후 2:58:16
0: OK
1: OK
2: OK
3: OK
4: OK
5: OK
6: OK

간단하죠? ^^ 추가적으로 Polly의 다양한 사용법은 다음의 글을 읽어보시면 도움이 되실 것입니다.

C# - Polly를 사용하여 탄력적인 응용 프로그램 만들기
; https://jacking75.github.io/NET_lib_polly/

(첨부 파일은 이 글의 예제 코드를 포함합니다.)




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 6/21/2023]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 61  [62]  63  64  65  66  67  68  69  70  71  72  73  74  75  ...
NoWriterDateCnt.TitleFile(s)
12426정성태11/24/202017399오류 유형: 685. WinDbg Preview - error InitTypeRead
12425정성태11/24/202019438VC++: 141. Visual C++ - "Treat Warnings As Errors" 옵션이 꺼져 있는데도 일부 경고가 에러 처리되는 경우
12424정성태11/24/202019675VC++: 140. C++의 연산자 동의어(operator synonyms), 대체 토큰 [1]
12423정성태11/22/202019692.NET Framework: 974. C# 9.0 - (16) 제약 조건이 없는 형식 매개변수 주석(Unconstrained type parameter annotations)파일 다운로드1
12422정성태11/21/202017168.NET Framework: 973. .NET 5, .NET Framework에서만 허용하는 UnmanagedCallersOnly 사용예파일 다운로드1
12421정성태11/19/202016235.NET Framework: 972. DNNE가 출력한 NE DLL을 직접 생성하는 방법파일 다운로드1
12420정성태11/19/202016810오류 유형: 684. Visual C++ - MSIL .netmodule or module compiled with /GL found; restarting link with /LTCG; add /LTCG to the link command line to improve linker performance
12419정성태11/19/202017088VC++: 139. Visual C++ - .NET Core의 nethost.lib와 정적 링크파일 다운로드1
12418정성태11/19/202019249오류 유형: 683. Visual C++ - error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MT_StaticRelease' doesn't match value 'MDd_DynamicDebug'파일 다운로드1
12417정성태11/19/202017731오류 유형: 682. Visual C++ - warning LNK4099: PDB '...pdb' was not found with '...lib(pch.obj)' or at '...pdb'; linking object as if no debug info
12416정성태11/19/202018855오류 유형: 681. Visual C++ - error LNK2001: unresolved external symbol _CrtDbgReport
12415정성태11/18/202018403.NET Framework: 971. UnmanagedCallersOnly 특성과 DNNE 사용파일 다운로드1
12414정성태11/18/202021189VC++: 138. x64 빌드에서 extern "C"가 아닌 경우 ___cdecl name mangling 적용 [4]파일 다운로드1
12413정성태11/17/202019800.NET Framework: 970. .NET 5 / .NET Core - UnmanagedCallersOnly 특성을 사용한 함수 내보내기파일 다운로드1
12412정성태11/16/202021836.NET Framework: 969. .NET Framework 및 .NET 5 - UnmanagedCallersOnly 특성 사용파일 다운로드1
12411정성태11/12/202018380오류 유형: 680. C# 9.0 - Error CS8889 The target runtime doesn't support extensible or runtime-environment default calling conventions.
12410정성태11/12/202019277디버깅 기술: 174. windbg - System.TypeLoadException 예외 분석 사례
12409정성태11/12/202020940.NET Framework: 968. C# 9.0의 Function pointer를 이용한 함수 주소 구하는 방법파일 다운로드1
12408정성태11/9/202035914도서: 시작하세요! C# 9.0 프로그래밍 [8]
12407정성태11/9/202020992.NET Framework: 967. "clr!JIT_DbgIsJustMyCode" 호출이 뭘까요?
12406정성태11/8/202021957.NET Framework: 966. C# 9.0 - (15) 최상위 문(Top-level statements) [5]파일 다운로드1
12405정성태11/8/202020519.NET Framework: 965. C# 9.0 - (14) 부분 메서드에 대한 새로운 기능(New features for partial methods)파일 다운로드1
12404정성태11/7/202021109.NET Framework: 964. C# 9.0 - (13) 모듈 이니셜라이저(Module initializers)파일 다운로드1
12403정성태11/7/202019106.NET Framework: 963. C# 9.0 - (12) foreach 루프에 대한 GetEnumerator 확장 메서드 지원(Extension GetEnumerator)파일 다운로드1
12402정성태11/7/202021422.NET Framework: 962. C# 9.0 - (11) 공변 반환 형식(Covariant return types) [1]파일 다운로드1
12401정성태11/5/202020735VS.NET IDE: 153. 닷넷 응용 프로그램에서의 "My Code" 범위와 "Enable Just My Code"의 역할 [1]
... 61  [62]  63  64  65  66  67  68  69  70  71  72  73  74  75  ...