gRPC - 인터셉터
2022. 5. 25. 00:00ㆍASPNET/Grpc
반응형
인터셉터는 앱이 들어오는 또는 나가는 gRPC 호출과 상호 작용할 수 있도록 하는 gRPC 개념으로,
요청 처리 파이프라인을 보강하는 방법을 제공합니다.
인터셉터는 채널 또는 서비스에 대해 구성되고 각 gRPC 호출에서 자동으로 실행됩니다.
인터셉터는 사용자의 애플리케이션 논리에 투명하므로
로깅, 모니터링, 인증, 유효성 검사와 같은 공통 사례에 적합한 솔루션입니다.
기본 코드
public class ExampleInterceptor : Interceptor
{
...
}
클라이언트 인터셉터
grpc server 로 나가는 rpc 호출을 가로챌 수 있다.
- BlockingUnaryCall: 단항 RPC의 차단 호출을 가로챕니다.
- AsyncUnaryCall: 단항 RPC의 비동기 호출을 가로챕니다.
- AsyncClientStreamingCall: 클라이언트 스트리밍 RPC의 비동기 호출을 가로챕니다.
- AsyncServerStreamingCall: 서버 스트리밍 RPC의 비동기 호출을 가로챕니다.
- AsyncDuplexStreamingCall: 양방향 스트리밍 RPC의 비동기 호출을 가로챕니다.
** 차단 호출과 비동기 호출은 서로 교환 하여 사용할 수 없다.
둘은 각각에 해당하는 call 만 가로챈다. 다른 call 에 대해 가로채지 않는다.
즉 UnaryCall 은 둘(blockingXXX or asyncXXX) 모두에서 intercept 되지 않는다. **
ClientInterceptor/ClientLoggingInterceptor.cs
using Grpc.Core;
using Grpc.Core.Interceptors;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
namespace GrpcClient.ClientInterceptor;
public class ClientLoggingInterceptor : Interceptor
{
public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(
TRequest request,
ClientInterceptorContext<TRequest, TResponse> context,
AsyncUnaryCallContinuation<TRequest, TResponse> continuation)
{
var options = new JsonSerializerOptions()
{
IncludeFields = true,
WriteIndented = true,
Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
};
var jsonData = JsonSerializer.Serialize<object>(request, options);
var message = $"Starting async unary call. Type: {context.Method.Type}. "
+ $"Method: {context.Method.Name}."
+ $"\nRequest => {jsonData}";
Console.WriteLine(message);
var responseResult = continuation(request, context);
var response = responseResult.ResponseAsync?.Result;
if (response != null)
jsonData = JsonSerializer.Serialize<object>(response, options);
else
jsonData = String.Empty;
message = $"\nResponse => {jsonData}";
Console.WriteLine(message);
return responseResult;
}
public override TResponse BlockingUnaryCall<TRequest, TResponse>(
TRequest request,
ClientInterceptorContext<TRequest, TResponse> context,
BlockingUnaryCallContinuation<TRequest, TResponse> continuation)
{
var options = new JsonSerializerOptions()
{
IncludeFields = true,
WriteIndented = true,
Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
};
var jsonData = JsonSerializer.Serialize<object>(request, options);
var message = $"Starting blocking unary call. Type: {context.Method.Type}. "
+ $"Method: {context.Method.Name}."
+ $"\nRequest => {jsonData}";
Console.WriteLine(message);
var response = continuation(request, context);
jsonData = JsonSerializer.Serialize<object>(response, options);
message = $"\nResponse => {jsonData}";
Console.WriteLine(message);
return response;
}
}
Program.cs
...
var invoker = channel.Intercept(new ClientLoggingInterceptor());
var client = new Greeter.GreeterClient(invoker);
var replyAsync = await client.SayHelloAsync(
new HelloRequest { Name = "나는 천재" });
Console.WriteLine("Async Greeting: " + replyAsync.Message);
var reply = client.SayHello(
new HelloRequest { Name = "나는 천재" });
Console.WriteLine("Block Greeting: " + reply.Message);
...
실행
서버 인터셉터
ServerInterceptor/ServerLoggingInterceptor.cs
using Grpc.Core;
using Grpc.Core.Interceptors;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
namespace GrpcServerWithASPNet.ServerInterceptor;
public class ServerLoggingInterceptor : Interceptor
{
private readonly ILogger _logger;
public ServerLoggingInterceptor(ILogger<ServerLoggingInterceptor> logger)
{
_logger = logger;
}
public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(
TRequest request,
ServerCallContext context,
UnaryServerMethod<TRequest, TResponse> continuation)
{
try
{
var options = new JsonSerializerOptions()
{
IncludeFields = true,
WriteIndented = true,
Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
};
var jsonData = JsonSerializer.Serialize<object>(request, options);
var message = $"Starting ServerLoggingInterceptor. Type: {MethodType.Unary}. "
+ $"Method: {context.Method}."
+ $"\nRequest => {jsonData}";
_logger.LogInformation(message);
var response = await continuation(request, context);
jsonData = JsonSerializer.Serialize<object>(response, options);
message = $"\nResponse => {jsonData}";
_logger.LogInformation(message);
return response;
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error thrown by {context.Method}.");
throw;
}
}
}
Program.cs
...
//builder.Services.AddGrpc();
builder.Services.AddGrpc(options =>
{
options.Interceptors.Add<ServerLoggingInterceptor>();
});
...
실행
관련영상
반응형
'ASPNET > Grpc' 카테고리의 다른 글
gRPC - 프로세스 간 통신 (IPC) (0) | 2022.05.27 |
---|---|
gRPC - 로깅 및 진단 (0) | 2022.05.26 |
gRPC - JWT Token 을 통한 인증 처리 (16) | 2022.05.24 |
gRPC - Configuration (0) | 2022.05.23 |
grpc test - grpcui (0) | 2022.05.20 |