[C#] Polly Nuget 패키지 - PolicyWrap

참조


PolicyWrap 란

  • PolicyWrap 이란, 이전에 정의된 정책들을 여러가지 결합된 정책 전략을 의미합니다.
  • 예를 들어, Retry 전략이 있고, Timeout 전략이 있을 경우 Retry 전략과 Timeout 전략을 합쳐서 사용하는 것을 의미합니다.
  • 그럼 예제를 통해서 PolicyWrap 를 알아 보도록 하겠습니다.

PolicyWrap Syntax

  • Polly 공식 문서에서 PolicyWrap 사용 예제 방법은 다음과 같습니다.
  • 아래 방식을 이용하여 시나리오를 구성하고, 직접 2개 이상의 전략을 Wrapping 해보겠습니다.
// Define a combined policy strategy, built of previously-defined policies.
var policyWrap = Policy
  .Wrap(fallback, cache, retry, breaker, timeout, bulkhead);
// (wraps the policies around any executed delegate: fallback outermost ... bulkhead innermost)
policyWrap.Execute(...)

// Define a standard resilience strategy ...
PolicyWrap commonResilience = Policy.Wrap(retry, breaker, timeout);

// ... then wrap in extra policies specific to a call site, at that call site:
Avatar avatar = Policy<UserAvatar>
   .Handle<FooException>()
   .Fallback<Avatar>(Avatar.Blank)
   .Wrap(commonResilience)
   .Execute(() => { /* get avatar */ });

// Share commonResilience, but wrap different policies in at another call site:
Reputation reps = Policy
   .Handle<FooException>()
   .Fallback<Reputation>(Reputation.NotAvailable)
   .Wrap(commonResilience)
   .Execute(() => { /* get reputation */ });  

시나리오

  • C# 으로 gRPC Server/Client 서비스를 생성하고 간단하게 로직을 구현합니다.

  • 여기서, Client 에서 Server 의 접속 정보를 다르게 하여 RpcException 이 발생하도록 합니다.

  • 실제 RpcException 에러가 발생 하였을 때, Polly 가 RpcException 에러를 감지하고 실제로 Timeout을 진행하는지 테스트 진행합니다.


Polly NuGet Package 설치

  • 먼저, C# Project 에 Polly NuGet Package 설치 진행합니다.

PMC 명령어 설치

  • NuGet Package Manager Command 로 설치할 경우, 다음 명령어로 설치 진행 가능합니다.
Install-Package Polly

NuGet Package 설치

  • Polly 검색후, 다음 아이콘으로 생긴 NuGet 을 설치 진행합니다.

    참고로, Polly 는 gRPC 프로젝트에서 Client 프로젝트에 설치 하였습니다. 저는 Client 에서 Server 의 접속이 끊어졌을 경우 테스트 하였기 때문에 Polly 패키지를 Client에 추가하였습니다.


Server 프로젝트 생성

  • gRPC Server 프로젝트는 ASP.NET Core gRPC 서비스 프로젝트로 생성하였습니다.
  • ASP.NET Core gRPC 서비스 프로젝트를 생성하게 되면, 기본으로 Protos 파일이 생성이 되고, 해당 디렉토리 안에 greet.proto 파일이 생성됩니다.
  • 또한, GreeterService.cs 클래스가 자동으로 생성되며, 해당 클래스 안에는 gRPC 서버 로직이 구현되어 있습니다.
  • 해당 프로젝트 생성 과정은 생략 하도록 하겠습니다.

Client 프로젝트 생성

  • Client 프로젝트는 콘솔 프로젝트 로 생성하였습니다.
  • 그리고 다음 3가지의 NuGet Package 를 설치 하였습니다.
    • Google.Protobuf
    • Grpc.Net.Client
    • Grpc.Tools
  • 위 3개의 NuGet Package를 설치 진행 되어야 gRPC 통신을 진행할 수 있습니다.

Client 에서 policyWrap 내용 추가

  • 앞서, gRPC Client 프로젝트를 추가하였습니다.
  • 다음으로, 실제 gRPC Server 에 연결하여 메시지를 보내는 코드를 추가하겠습니다.
  • 아래 코드에서는 총 2개의 정책을 추가하였습니다.
  • 첫 번째 정책은 retry 정책이고, 두 번째 정책은 timeout 정책입니다.
  • 그리고 2개의 정책을 WrapAsync 을 통해서 Wrapping 해주고 있습니다.
  • 아래 예제 코드는, retry 시도하는 로직이 특정 초(현재 예제 코드에서는 2초) 이상이 걸리는 경우 Timeout 발생하여 그대로 프로그램을 종료할 수 있게 해주는 예제코드입니다.
using Grpc.Core;
using Grpc.Net.Client;
using gRPCService;
using Polly;
using Polly.Timeout;

// Retry 정책
var retryPolly = Policy
           .Handle<RpcException>()
           .RetryAsync(3, (exception, retryCount, context) =>
           {
               Console.WriteLine($"try: {retryCount}, Exception: {exception.Message}");
           });

// Timeout 정책
var timeoutPolicy = Policy
    .TimeoutAsync(TimeSpan.FromSeconds(2), TimeoutStrategy.Pessimistic,
    async (context, timespan, task) =>
    {
        // Add extra logic to be invoked when a timeout occurs, such as logging
        Console.WriteLine($"Retry 중 Timeout 발생");
    });

var policyWrap = retryPolly.WrapAsync(timeoutPolicy);

var result = await policyWrap.ExecuteAsync(async () => await DoSomething());

/// <summary>
/// gRPC Server 에게 메시지 보내기
/// </summary>
static async Task<string> DoSomething()
{
    Console.WriteLine($"{nameof(DoSomething)} has been called.");

    var channel = GrpcChannel.ForAddress("https://localhost:7243");
    var greeterClient = new Greeter.GreeterClient(channel);

    var greeterRequest = new HelloRequest { Name = "Beom" };

    var greeter = await greeterClient.SayHelloAsync(greeterRequest);

    Console.WriteLine($"{greeter.Message}");

    Console.WriteLine($"Successfully send request");

    return greeter.Message;
}

실행 결과

  • 실행 결과, 첫 번째 Retry 하는 중에 2초 이상의 로직 시간이 소요되어 그 안에서 2번째 정책인 Timeout 정책이 발효되어 Retry 중 Timeout 발생 메시지 출력과 함께 프로그램이 그대로 에러를 발생시켜 종료하는 것을 확인할 수 있습니다.
DoSomething has been called.
Retry 중 Timeout 발생
728x90

이 글을 공유하기

댓글

Designed by JB FACTORY