성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] VT sequences to "CONOUT$" vs. STD_O...
[정성태] NetCoreDbg is a managed code debugg...
[정성태] Evaluating tail call elimination in...
[정성태] What’s new in System.Text.Json in ....
[정성태] What's new in .NET 9: Cryptography ...
[정성태] 아... 제시해 주신 "https://akrzemi1.wordp...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
[이승준] 완전히 잘못 짚었습니다. 댓글 지우고 싶네요. 검색을 해보...
[정성태] 우선 답글 감사합니다. ^^ 그런데, 사실 저 예제는 (g...
[이승준] 수정이 안되어서... byteArray는 BYTE* 타입입니다...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>C# - Polly를 이용한 클라이언트 측의 요청 재시도</h1> <p> 지난 글에서, <br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C# - 서버 측의 요청 제어 (Microsoft.AspNetCore.RateLimiting) ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/13362'>https://www.sysnet.pe.kr/2/0/13362</a> </pre> <br /> Microsoft.AspNetCore.RateLimiting을 사용해 요청 제어를 하는 방법을 설명했는데요, 이런 서비스를 이용하는 클라이언트는 반대로 제한이 걸린 서비스에 대한 호출을 재시도해야 합니다.<br /> <br /> 파이썬의 경우, 이럴 때 <a target='tab' href='https://pypi.org/project/tenacity/'>Tenacity</a>, <a target='tab' href='https://pypi.org/project/backoff/'>backoff</a> 등의 패키지를 이용해 간단한 특성 처리를 할 수 있는데요,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > import openai # for OpenAI API calls from tenacity import ( retry, stop_after_attempt, wait_random_exponential, ) # for exponential backoff <span style='color: blue; font-weight: bold'>@retry(wait=wait_random_exponential(min=1, max=60), stop=stop_after_attempt(6))</span> def completion_with_backoff(**kwargs): return openai.Completion.create(**kwargs) completion_with_backoff(model="text-davinci-002", prompt="Once upon a time,") </pre> <br /> 닷넷의 경우에는 Polly 라이브러리를 이용해,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Polly ; <a target='tab' href='https://www.nuget.org/packages/polly/'>https://www.nuget.org/packages/polly/</a> App-vNext/Polly ; <a target='tab' href='https://github.com/App-vNext/Polly#installing-via-the-net-sdk'>https://github.com/App-vNext/Polly#installing-via-the-net-sdk</a> Implement HTTP call retries with exponential backoff with IHttpClientFactory and Polly policies ; <a target='tab' href='https://learn.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/implement-http-call-retries-exponential-backoff-polly'>https://learn.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/implement-http-call-retries-exponential-backoff-polly</a> </pre> <br /> (비록 특성을 지정하는 것처럼 간단하게는 아니지만) 유사하게 구현할 수 있습니다.<br /> <br /> 예를 들어, 지수 단위로 대기 시간이 늘어나는 Polly 정책은 (<a target='tab' href='https://github.com/App-vNext/Polly#installing-via-the-net-sdk'>문서</a>에서 나온 것 중에서) 다음과 같이 코딩할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // 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))); </pre> <br /> 이것을 적용해 지난 글에서 다룬 Rate Limit가 걸린 서비스를 호출하는 예제 클라이언트 코드를 다음과 같이 재작성할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using Polly; using System.Net; namespace ConsoleApp1; internal class Program { public const int MaxRequests = 7; static async Task<int> Main(string[] args) { <span style='color: blue; font-weight: bold'>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))); });</span> var client = new HttpClient(); var context = new Context(); var requests = new Task<HttpResponseMessage>[MaxRequests]; for (int i = 0; i < MaxRequests; i++) { requests[i] = <span style='color: blue; font-weight: bold'>retryPolicy.ExecuteAsync(async ctx => { return await client.GetAsync("http://localhost:5203/WeatherForecast"); }, context);</span> } await Task.WhenAll(requests); for (int i = 0; i < MaxRequests; i++) { Console.WriteLine($"{i}: {requests[i].Result.StatusCode}"); } return 0; } } </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 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 </pre> <br /> 간단하죠? ^^ 추가적으로 Polly의 다양한 사용법은 다음의 글을 읽어보시면 도움이 되실 것입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C# - Polly를 사용하여 탄력적인 응용 프로그램 만들기 ; <a target='tab' href='https://jacking75.github.io/NET_lib_polly/'>https://jacking75.github.io/NET_lib_polly/</a> </pre> <br /> (<a target='tab' href='https://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=2092&boardid=331301885'>첨부 파일은 이 글의 예제 코드를 포함</a>합니다.)<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1266
(왼쪽의 숫자를 입력해야 합니다.)