ASP.NET Core gRPC 攔截器

gRPC 作爲一套獨立的 RPC 框架,像攔截器這種功能當然也是不可或缺的,框架自帶的攔截器更多是基於框架本身出發,對於 gRPC 來說最突出的就是需要支持各種不同 RPC 調用方式的攔截,如:簡單 RPC 調用流式 RPC 調用,流式調用又分 客戶端流式調用服務端流式調用雙向流式調用,關於流式調用更多介紹可參考:ASP.NET Core gRPC 流式調用

攔截器分類

不論是基於 .NET Core 2.x 或 3.x,都需要依賴 Grpc.Core 這個 NuGet Package,Grpc.Core 中已提供攔截器(Interceptor 類)功能(不過如果使用的版本過低,可能不支持攔截器,我們之前經歷過這個階段)。攔截器中的方法分兩類,分別作用於客戶端(客戶端向服務端發請求時攔截) 和 服務端(服務端接收到客戶端請求時攔截)。

服務端相關攔截方法:

// 簡單調用攔截
public virtual Task<TResponse> UnaryServerHandler<TRequest, TResponse>(TRequest request, ServerCallContext context, UnaryServerMethod<TRequest, TResponse> continuation)

// 客戶端流式調用攔截
public virtual Task<TResponse> ClientStreamingServerHandler<TRequest, TResponse>(IAsyncStreamReader<TRequest> requestStream, ServerCallContext context, ClientStreamingServerMethod<TRequest, TResponse> continuation)

// 服務端流式調用攔截
public virtual Task ServerStreamingServerHandler<TRequest, TResponse>(TRequest request, IServerStreamWriter<TResponse> responseStream, ServerCallContext context, ServerStreamingServerMethod<TRequest, TResponse> continuation)

// 雙向流調用攔截
public virtual Task DuplexStreamingServerHandler<TRequest, TResponse>(IAsyncStreamReader<TRequest> requestStream, IServerStreamWriter<TResponse> responseStream, ServerCallContext context, DuplexStreamingServerMethod<TRequest, TResponse> continuation)

客戶端相關攔截方法:

// 同步簡單調用攔截
public virtual TResponse BlockingUnaryCall<TRequest, TResponse>(TRequest request, ClientInterceptorContext<TRequest, TResponse> context, BlockingUnaryCallContinuation<TRequest, TResponse> continuation)

// 異步簡單調用攔截
public virtual AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(TRequest request, ClientInterceptorContext<TRequest, TResponse> context, AsyncUnaryCallContinuation<TRequest, TResponse> continuation)

// 異步服務端流式調用攔截
public virtual AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(TRequest request, ClientInterceptorContext<TRequest, TResponse> context, AsyncServerStreamingCallContinuation<TRequest, TResponse> continuation)

// 異步客戶端流式調用攔截
public virtual AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(ClientInterceptorContext<TRequest, TResponse> context, AsyncClientStreamingCallContinuation<TRequest, TResponse> continuation)

// 異步雙向流調用攔截
public virtual AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(ClientInterceptorContext<TRequest, TResponse> context, AsyncDuplexStreamingCallContinuation<TRequest, TResponse> continuation)

服務端攔截器實現

創建 ServerInterceptor 繼承於抽象類 Interceptor,這裏通過實現簡單調用的服務端攔截方法 UnaryServerHandler 進行說明,最終需按實際開發情況實現更多攔截方法。

public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(TRequest request, ServerCallContext context, UnaryServerMethod<TRequest, TResponse> continuation)
{
  Console.WriteLine("服務端執行開始");
  var response = await continuation(request, context);
  Console.WriteLine("服務端執行結束");
  return response;
}

客戶端攔截器實現

創建 ClientInterceptor 繼承於抽象類 Interceptor,這裏通過實現 同步/異步 客戶端簡單調用的攔截方法 BlockingUnaryCallAsyncUnaryCall 進行說明,最終需按實際開發情況實現更多攔截方法。

public override TResponse BlockingUnaryCall<TRequest, TResponse>(TRequest request, ClientInterceptorContext<TRequest, TResponse> context, BlockingUnaryCallContinuation<TRequest, TResponse> continuation)
{
  Console.WriteLine("客戶端調用執行開始");
  var response = continuation(request, context);
  Console.WriteLine("客戶端調用執行結束");
  return response;
}

public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(TRequest request, ClientInterceptorContext<TRequest, TResponse> context, AsyncUnaryCallContinuation<TRequest, TResponse> continuation)
{
  Console.WriteLine("客戶端調用執行開始");
  var responseCon = continuation(request, context);
  var response = new AsyncUnaryCall<TResponse>(responseCon.ResponseAsync, responseCon.ResponseHeadersAsync, responseCon.GetStatus, responseCon.GetTrailers, responseCon.Dispose);
  Console.WriteLine("客戶端調用執行結束");
  return response;
}

攔截器配置

.NET Core 3.0 後配置方式如下:

服務端配置攔截器可通過在 ConfigureServices 中通過 services.AddGrpc 中的 GrpcServiceOptions 來指定 Interceptors,如下:

services.AddGrpc(options =>
{
  options.Interceptors.Add<ServerInterceptor>();
});

客戶端配置攔截通過 channelIntercept 方法,如下:

var channel = GrpcChannel.ForAddress("https://localhost:5001");
var invoker = channel.Intercept(new ClientInterceptor());
var client = new Greeter.GreeterClient(invoker);

服務端和服務端攔截器的配置都可支持多個,如果同時指定多個攔截器會按照添加順序依次執行

參考鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章