1. 程式人生 > >ASP.NET Core 3.0 gRPC 攔截器

ASP.NET Core 3.0 gRPC 攔截器

目錄

  • ASP.NET Core 3.0 使用gRPC
  • ASP.NET Core 3.0 gRPC 雙向流
  • ASP.NET Core 3.0 gRPC 攔截器

一. 前言

前面兩篇文章給大家介紹了使用gRPC的入門以及雙向流的使用,今天介紹的是gRPC中的攔截器。攔截器就像MVC的過濾器或者是ASP.NET Core middleware 一樣,具有面向切面的思想,可以在呼叫服務的時候進行一些統一處理, 很適合在這裡處理驗證、日誌等流程。本片文章就以記錄日誌為例來進行講解。

二. Interceptor 類介紹

Interceptor類是gRPC服務攔截器的基類,是一個抽象類,它定了幾個虛方法,分別如下:

public virtual TResponse BlockingUnaryCall<TRequest, TResponse>();
public virtual AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>();
public virtual AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>();
public virtual AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>();
public virtual AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>();
public virtual Task<TResponse> UnaryServerHandler<TRequest, TResponse>();
public virtual Task<TResponse> ClientStreamingServerHandler<TRequest, TResponse>();
public virtual Task ServerStreamingServerHandler<TRequest, TResponse>();
public virtual Task DuplexStreamingServerHandler<TRequest, TResponse>();

各個方法作用如下:

方法名稱 作用
BlockingUnaryCall 攔截阻塞呼叫
AsyncUnaryCall 攔截非同步呼叫
AsyncServerStreamingCall 攔截非同步服務端流呼叫
AsyncClientStreamingCall 攔截非同步客戶端流呼叫
AsyncDuplexStreamingCall 攔截非同步雙向流呼叫
UnaryServerHandler 用於攔截和傳入普通呼叫伺服器端處理程式
ClientStreamingServerHandler 用於攔截客戶端流呼叫的伺服器端處理程式
ServerStreamingServerHandler 用於攔截服務端流呼叫的伺服器端處理程式
DuplexStreamingServerHandler 用於攔截雙向流呼叫的伺服器端處理程式

在實際使用中,可以根據自己的需要來使用對應的攔截方法。

三. 客戶端攔截器

基於前面兩篇文章使用的Demo。

在客戶端專案新建一個類,命名為 ClientLoggerInterceptor,繼承攔截器基類 Interceptor

我們在前面使用的Demo,定義了擼貓服務,其中 SuckingCatAsync方法為非同步呼叫,所以我們重寫攔截器的 AsyncUnaryCall方法

public class ClientLoggerInterceptor:Interceptor
{
    public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(
        TRequest request,
        ClientInterceptorContext<TRequest, TResponse> context,
        AsyncUnaryCallContinuation<TRequest, TResponse> continuation)
    {
        LogCall(context.Method);

        return continuation(request, context);
    }

    private void LogCall<TRequest, TResponse>(Method<TRequest, TResponse> method)
        where TRequest : class
        where TResponse : class
    {
        var initialColor = Console.ForegroundColor;
        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine($"Starting call. Type: {method.Type}. Request: {typeof(TRequest)}. Response: {typeof(TResponse)}");
        Console.ForegroundColor = initialColor;
    }
}

註冊攔截器:

var channel = GrpcChannel.ForAddress("https://localhost:5001");
var invoker = channel.Intercept(new ClientLoggerInterceptor());
var catClient = new LuCat.LuCatClient(invoker);
var catReply = await catClient.SuckingCatAsync(new Empty());
Console.WriteLine("呼叫擼貓服務:"+ catReply.Message);

然後執行:

可以看到成功的在客戶端攔截到了呼叫,並記錄了呼叫資訊。

四. 服務端攔截器

在服務端專案新建一個類,命名為 ServerLoggerInterceptor,繼承攔截器基類 Interceptor

我們在服務端需要實現的方法是 UnaryServerHandler

public class ServerLoggerInterceptor: Interceptor
{
    private readonly ILogger<ServerLoggerInterceptor> _logger;

    public ServerLoggerInterceptor(ILogger<ServerLoggerInterceptor> logger)
    {
        _logger = logger;
    }

    public override Task<TResponse> UnaryServerHandler<TRequest, TResponse>(
        TRequest request,
        ServerCallContext context,
        UnaryServerMethod<TRequest, TResponse> continuation)
    {
        LogCall<TRequest, TResponse>(MethodType.Unary, context);
        return continuation(request, context);
    }

    private void LogCall<TRequest, TResponse>(MethodType methodType, ServerCallContext context)
        where TRequest : class
        where TResponse : class
    {
        _logger.LogWarning($"Starting call. Type: {methodType}. Request: {typeof(TRequest)}. Response: {typeof(TResponse)}");
    }
}

註冊攔截器:

public void ConfigureServices(IServiceCollection services)
{
    services.AddGrpc(options =>
    {
        options.Interceptors.Add<ServerLoggerInterceptor>();
    });
}

執行:

可以看到服務端成功攔截到了,客戶端的呼叫。

五. 參考資料

.NET Core 上的 gRPC 的簡介

本文Demo