C# Grpc-AOP編程攔截器(Interceptor)

文檔不全仍需要補(bǔ)充,具體可以參考 Grpc.Core.Api/Interceptors

.Net 中的 Grpc 是在 v1.10.0 版本 起支持 AOP .源碼中看到是2018年2月12日 傳上去的pre 版
Grpc預(yù)留給開發(fā)者 抽象類 Interceptor(位于命名空間 Grpc.Core.Interceptors),攔截功能主要在該類中實(shí)現(xiàn)
通過(guò)它可以做架構(gòu)上很多事情,這是Grpc深入時(shí)必須掌握的
可以做日志、監(jiān)控、權(quán)限控制、還可以做 tag緩存。

服務(wù)端攔截器 實(shí)現(xiàn)方式(以簡(jiǎn)單模式為例)

A、定義攔截器類:override Interceptor抽象類的 UnaryServerHandler(簡(jiǎn)單模式) 方法
B、實(shí)現(xiàn)攔截器方法:在 調(diào)用 continuation(request, context); 前后實(shí)現(xiàn) 攔截功的代碼
C、使用攔截器:在 創(chuàng)建服務(wù)時(shí),使用BindService(**).Intercept(new 自定義攔截器) 。

注:continuation(request, context) 就是會(huì)直接進(jìn)入 我們實(shí)現(xiàn)的業(yè)務(wù)代碼 Grpc服務(wù)中。
注:可重寫方法有:客戶端流模式(ClientStreamingServerHandler)、服務(wù)器端流模式(ServerStreamingServerHandler)、雙向模式的攔截(DuplexStreamingServerHandler)

A 定義攔截器類 : ServerCallContextInterceptor .cs

public class ServerCallContextInterceptor : Interceptor
{
    #region Override Methods
    public override Task<TResponse> UnaryServerHandler<TRequest, TResponse>(TRequest request, ServerCallContext context, UnaryServerMethod<TRequest, TResponse> continuation)
    {
             // B、實(shí)現(xiàn)攔截器方法
             // 寫請(qǐng)求 成功前 的代碼
             // 獲取 客戶端傳來(lái)的自定義報(bào)頭(參考客戶端攔截器實(shí)現(xiàn))
             context.RequestHeaders.Last(m => (m.Key == "Surf-Token")).Value;
             context.RequestHeaders.Last(m => (m.Key == "RequestId")).Value;

            return continuation(request, context);
             // 寫請(qǐng)求 完成后 的代碼
             // 或向 客戶端附加 一些信息
             // 也可以 用try catch 做異常日志
             // 可以從 context中取出 調(diào)用方ip,做ip限制
             // 可以 監(jiān)控continuation 的 執(zhí)行時(shí)間
    }
    //... 可重寫 客戶端流模式(ClientStreamingServerHandler)、服務(wù)器端流模式(ServerStreamingServerHandler)、雙向模式的攔截(DuplexStreamingServerHandler)
        #endregion
    }

C、使用攔截器:BindService(**).Intercept(new 自定義攔截器)在程序啟動(dòng)時(shí) Program.cs

Main()
{
    var userGService = UserService.BindService(EngineContext.Resolve<UserServiceBase>());

    var server = new Server(channelOptions)
    {
        Services = {
           userGService.Intercept(new ServerCallContextInterceptor()),
        },
        Ports = { new ServerPort(AppSettings.Host, AppSettings.Port, ServerCredentials.Insecure) }
    };
    server.Start();
}

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

客戶端是在Channel上實(shí)現(xiàn)攔截器的,當(dāng)new Channel()后就可以調(diào)用 Channel.Intercept方法
Intercept 方法有兩個(gè)重載 :

A、一個(gè)接受收委托,在委托中實(shí)現(xiàn)攔截器代碼
??????CallInvoker Intercept(this ChannelBase channel, Func<Metadata, Metadata> interceptor)
B、一個(gè)接收 攔截器數(shù)組,需自定義攔截器
??????CallInvoker Intercept(this ChannelBase channel, params Interceptor[] interceptors)

A、接受收委托的方式: Intercept(... Func<Metadata, Metadata> interceptor) 方法的使用

代碼里主要是用于增加發(fā)送的報(bào)頭,代碼如:

var channel = new Channel("127.0.0.1",8001);
channel.Intercept(metadata =>
            {
                metadata = metadata ?? new Metadata();
                metadata.Add(new Metadata.Entry("RequestId", "我是 明道云AI服務(wù) 在調(diào)用您 "));
                metadata.Add(new Metadata.Entry("Surf-Token", "我是調(diào)用密鑰"));
                return metadata;
            });

B、一個(gè)接收 攔截器數(shù)組:Intercept(... params Interceptor[] ) 方法的使用

服務(wù)端實(shí)現(xiàn)攔截器的方法相同,需要 override Interceptor抽象類的幾個(gè)方法,如:BlockingUnaryCall、AsyncUnaryCall、AsyncClientStreamingCall等。

調(diào)用方法 仍是 channel.Intercept,如 channel.Intercept(new ClientCallContextInterceptor());

ClientCallContextInterceptor的實(shí)現(xiàn)參考上面 ServerCallContextInterceptor,僅是重寫的方法不同。

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

相關(guān)閱讀更多精彩內(nèi)容

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