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);

然后運行:

image-20191112105159256

可以看到成功的在客戶端攔截到了調用,並記錄了調用信息。

四. 服務端攔截器

在服務端項目新建一個類,命名為 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>();
    });
}

運行:

image-20191112110227838

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

五. 參考資料

.NET Core 上的 gRPC 的簡介

本文Demo


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM