Kitex Middleware 擴展

2022-04-27 10:19 更新

介紹

Middleware 是擴展 Kitex 框架的一個主要的方法,大部分基于 Kitex 的擴展和二次開發(fā)的功能都是基于 middleware 來實現(xiàn)的。

在擴展過程中,要記得兩點原則:

  1. 中間件和套件都只允許在初始化 Server、Client 的時候設置,不允許動態(tài)修改。
  2. 后設置的會覆蓋先設置的。

Kitex 的中間件定義在 ?pkg/endpoint/endpoint.go? 中,其中最主要的是兩個類型:

  1. ?Endpoint ?是一個函數(shù),接受 ctx、req、resp,返回 err,可參考下方示例;
  2. ?Middleware?(下稱 MW)也是一個函數(shù),接收同時返回一個 ?Endpoint?。

實際上一個中間件就是一個輸入是 ?Endpoint?,輸出也是 ?Endpoint ?的函數(shù),這樣保證了對應用的透明性,應用本身并不會知道是否被中間件裝飾的。由于這個特性,中間件可以嵌套使用。

中間件是串連使用的,通過調(diào)用傳入的 next,可以得到后一個中間件返回的 response(如果有)和 err,據(jù)此作出相應處理后,向前一個中間件返回 err(務必判斷 next err 返回,勿吞了 err)或者設置 response。

客戶端中間件

有兩種方法可以添加客戶端中間件:

  1. ?client.WithMiddleware? 對當前 client 增加一個中間件,在其余所有中間件之前執(zhí)行;
  2. ?client.WithInstanceMW? 對當前 client 增加一個中間件,在服務發(fā)現(xiàn)和負載均衡之后執(zhí)行(如果使用了 Proxy 則不會調(diào)用到)。

注意,上述函數(shù)都應該在創(chuàng)建 client 時作為傳入的 ?Option?。

客戶端中間件調(diào)用順序 :

  1. ?client.WithMiddleware? 設置的中間件
  2. ACLMiddleware
  3. (ResolveMW + client.WithInstanceMW + PoolMW / DialerMW) / ProxyMW
  4. IOErrorHandleMW

調(diào)用返回的順序則相反。

客戶端所有中間件的調(diào)用順序可以看 ?client/client.go?。

服務端中間件

服務端的中間件和客戶端有一定的區(qū)別。

可以通過 ?server.WithMiddleware? 來增加 server 端的中間件,使用方式和 client 一致,在創(chuàng)建 server 時通過 ?Option ?傳入。

總的服務端中間件的調(diào)用順序可以看 ?server/server.go?。

示例

我們可以通過以下這個例子來看一下如何使用中間件。

假如我們現(xiàn)在有需求,需要在請求前打印出 request 內(nèi)容,再請求后打印出 response 內(nèi)容,可以編寫如下的 MW:

func PrintRequestResponseMW(next endpoint.Endpoint) endpoint.Endpoint {
    return func(ctx context.Context, request, response interface{}) error {
        fmt.Printf("request: %v\n", request)
        err := next(ctx, request, response)
        fmt.Printf("response: %v", response)
        return err
    }
}

假設我們是 Server 端,就可以使用 ?server.WithMiddleware(PrintRequestResponseMW)? 來使用這個 MW 了。

以上方案僅為示例,不可用于生產(chǎn),會有性能問題。

注意事項

如果自定義 middleware 中用到了 RPCInfo,要注意 RPCInfo 在 rpc 結(jié)束之后會被回收,所以如果在 middleware 中起了 goroutine 操作 RPCInfo 會出問題,不能這么做。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號