.NET Core gRPC 攔截器

gRPC 作為一套獨(dú)立的 RPC 框架,像攔截器這種功能當(dāng)然也是不可或缺的,框架自帶的攔截器更多是基于框架本身出發(fā),對于 gRPC 來說最突出的就是需要支持各種不同 RPC 調(diào)用方式的攔截,如:簡單 RPC 調(diào)用、流式 RPC 調(diào)用,流式調(diào)用又分 客戶端流式調(diào)用、服務(wù)端流式調(diào)用、雙向流式調(diào)用,關(guān)于流式調(diào)用更多介紹可參考:ASP.NET Core gRPC 流式調(diào)用。

攔截器分類

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

服務(wù)端相關(guān)攔截方法:

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

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

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

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

客戶端相關(guān)攔截方法:

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

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

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

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

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

服務(wù)端攔截器實(shí)現(xiàn)

創(chuàng)建 ServerInterceptor 繼承于抽象類 Interceptor,這里通過實(shí)現(xiàn)簡單調(diào)用的服務(wù)端攔截方法 UnaryServerHandler 進(jìn)行說明,最終需按實(shí)際開發(fā)情況實(shí)現(xiàn)更多攔截方法。

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

客戶端攔截器實(shí)現(xiàn)

創(chuàng)建 ClientInterceptor 繼承于抽象類 Interceptor,這里通過實(shí)現(xiàn) 同步/異步 客戶端簡單調(diào)用的攔截方法 BlockingUnaryCallAsyncUnaryCall 進(jìn)行說明,最終需按實(shí)際開發(fā)情況實(shí)現(xiàn)更多攔截方法。

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

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

攔截器配置

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

服務(wù)端配置攔截器可通過在 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);

服務(wù)端和服務(wù)端攔截器的配置都可支持多個(gè),如果同時(shí)指定多個(gè)攔截器會按照添加順序依次執(zhí)行

result

參考鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容