Dubbo——過濾器概述

Dubbo過濾器概述

Dubbo中的過濾器和Web應用中的過濾器的概念是一樣的,提供了在服務調用前後插入自定義邏輯的途徑。過濾器是整個Dubbo框架中非常重要的組成部分,Dubbo中很多功能都是基於過濾器擴展而來的。過濾器提供了服務提供者和消費者調用過程的攔截,即每次都執行RPC調用的時候,對應的過濾器都會生效。雖然過濾器的功能強大,但由於每次調用時都會執行,因此在使用的時候需要注意它對性能的影響。

過濾器的使用

  • 一種方式是使用@Active註解默認啓用;
  • 一種方式是在配置文件中配置;
<!-- 消費方調用過程攔截 -->
<dubbo:reference filter="xxx, yyy" />

<!-- 消費方調用過程默認攔截器,將攔截所有reference -->
<dubbo:consumer filter="xxx, yyy" />

<!-- 服務提供方調用過程攔截 -->
<dubbo:service filter="xxx, yyy" />

<!-- 服務提供方調用過程默認攔截器,將攔截所有service -->
<dubbo:provider filter="xxx, yyy" />

配置上的“潛規則”:

  1. 過濾器順序:

    • 用戶自定義的過濾器的順序默認會在框架內置過濾器之後,可以使用filter="xxx, default"這種配置方式讓自定義的過濾器順序靠前。
    • 我們在配置filter="xxx, yyy"時,寫在前面的xxx會比yyy的順序要靠前。
  2. 剔除過濾器。對於一些默認的過濾器或自動激活的過濾器,有些方法不想使用這些過濾器,可以使用"-"加過濾器名稱來過濾,如filter="-xxFilter"會讓xxFilter不生效。如果不想使用所有默認啓用的過濾器,則可以配置filter="-default"來進行剔除。

  3. 過濾器的疊加。如果服務提供者、消費者端都配置了過濾器,則兩邊的過濾器不會相互覆蓋,而是互相疊加,都會生效。如果需要覆蓋,則可以在消費方使用"-"的方式剔除對應的過濾器。

過濾器的總體結構

在這裏插入圖片描述

所有的內置過濾器中除了CompatibleFilter特別突出,只繼承了Filter接口,既不會被默認激活,其他的內置過濾器都使用了Activate註解,即默認被激活。Filter接口上有@SPI註解,說明過濾器是一個擴展點,用戶可以基於這個擴展點接口實現自己的過濾器。

所有的過濾器會被分爲消費者和服務提供者兩種類型,消費者類型的過濾器只會在服務引用時被加入Inoker,服務提供者類型的過濾器只會在服務暴露的時候被加入對應的Invoker。MonitorFilter比較特殊,它會同時在暴露和引用被加入Invoker。

過濾器名 作用 使用方
AccessLogFilter 打印每一次請求的訪問日誌。如果需要訪問的日誌只出現在指定的appender中,則可以在log的配置文件中配置additivity 服務提供者
ActiveLimitFilter 用於限制消費者端對服務的最大並行調用數 消費者
ExecuteLimitFilter 同上,用於限制服務端的最大並行調用數」服務提供者
ClassLoaderFilter 用於切換不同線程的類加載器,服務調用完成後會還原回去 服務提供者
CompatibleFilter 用戶使返回值與調用程序的對象版本兼容,默認不啓用。如果啓用,則會把JSON或fastjson類型的返回值轉換爲Map類型;如果返回類型和本地接口中定義的不同,則會做POJO的轉換 -
ConsumerContextFilter 爲消費者把一些上下文信息設置到當前線程的RpcContext對象中,包括invocation、localhost、remote host等 消費者
ContextFilter 同上,但是爲服務提供者服務 服務提供者
DeprecatedFilter 如果調用的方法被標記位已棄用,那麼DeprecatedFilter將記錄一個錯誤消息 消費者
EchoFilter 用於echo測試 服務提供者
ExceptionFilter 用於統一的異常處理,防止出現序列化失敗 服務提供者
GenericFilter 用於服務提供者端,實現泛化調用,實現序列化的檢查和處理 服務提供者
GenericImplFilter 同上,但用於消費者端 消費者
TimeoutFilter 如果某些服務調用超時,則自動記錄告警日誌 服務提供者
TokenFilter 服務提供者下令發牌給消費者,通常用於防止消費者繞過註冊中心直接調用服務提供者 服務提供者
TpsLimitFilter 用於服務端的限流,注意與ExecuteLimitFilter 消費者
FutureFilter 在發起invoke或得到返回值、出現異常的時候觸發回調事件 消費者
TraceFilter Trace指令的使用 服務提供者
MonitorFilter 監控並統計所有的接口的調用情況,如成功、失敗、耗時。後續DubboMonitor會定時把該過濾器收集的數據發送到Dubbo-Monitor服務上 服務提供者+消費者

每個過濾器的使用方不一樣,有的是服務提供者使用,有的是消費者使用。Dubbo是如何保證服務提供者不會使用消費者的過濾器的呢?答案就在@Activate註解上,該註解可以設置過濾器激活的條件和順序,如@Activate(group = Constants.PROVIDER, order = -110000)表示在服務提供端擴展點實現纔有效,並且過濾器的順序是 -110000.

過濾器初始化的實現原理

服務的暴露與引用會使用Protocol層,而ProtocolFilterWrapper包裝類則實現了過濾器鏈的組裝。在服務的暴露與引用過程中,會使用ProtocolFilterWrapper#buildInvokerChain方法組裝整個過濾器鏈:

在這裏插入圖片描述

buildInvokerChain方法構造調用鏈的步驟:

  1. 獲取並遍歷所有過濾器。通過ExtensionLoader#getActivateExtension方法獲取所有的過濾器並遍歷。
  2. 使用裝飾器模式,增強原有Invoker,組裝過濾器鏈。使用裝飾器模式,像俄羅斯套娃一樣,把過濾器一個又一個套到Invoker上。

在這裏插入圖片描述

爲什麼要倒排遍歷呢?

因爲是通過從裏到外構造匿名類的方式構造Invoekr的,所以只有倒排,最外層的Invoker才能是第一個過濾器。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章