天天看點

dubbo源碼分析總結

前言

在進行源碼分析之前,我們先來通過一張圖了解 Dubbo 服務調用過程。

dubbo源碼分析總結

首先服務消費者通過代理對象 Proxy 發起遠端調用,接着通過網絡用戶端 Client 将編碼後的請求發送給服務提供方的網絡層上,也就是 Server。Server 在收到請求後,首先要做的事情是對資料包進行解碼。然後将解碼後的請求發送至分發器 Dispatcher,再由分發器将請求派發到指定的線程池上,最後由線程池調用具體的服務。這就是一個遠端調用請求的發送與接收過程。

SPI 機制

SPI 全稱為 Service Provider Interface,是一種服務發現機制。SPI 的本質是将接口實作類的全限定名配置在檔案中,并由服務加載器讀取配置檔案,加載實作類。這樣可以在運作時,動态為接口加載實作類。正是以特性,我們可以很容易的通過 SPI 機制為我們的程式提供拓展功能。SPI 機制在第三方架構中也有所應用,比如 Dubbo 就是通過 SPI 機制加載所有的元件。不過,Dubbo 并未使用 Java 原生的 SPI 機制,而是對其進行了增強,使其能夠更好的滿足需求。在 Dubbo 中,SPI 是一個非常重要的子產品。

Dubbo SPI 對 Java SPI 的改進

  • JDK 标準的 SPI 會一次性執行個體化擴充點所有實作,如果有擴充實作初始化很耗時,但如果沒用上也加載,會很浪費資源。
  • 如果擴充點加載失敗,連擴充點的名稱都拿不到了。比如:JDK 标準的 ScriptEngine,通過 getName()

    擷取腳本類型的名稱,但如果 RubyScriptEngine 因為所依賴的 jruby.jar 不存在,導緻

    RubyScriptEngine 類加載失敗,這個失敗原因被吃掉了,和 ruby 對應不起來,當使用者執行 ruby 腳本時,會報不支援

    ruby,而不是真正失敗的原因。

  • 增加了對擴充點 IOC 和 AOP 的支援,一個擴充點可以直接 setter 注入其它擴充點。

服務導出

Dubbo 服務導出過程始于 Spring 容器釋出重新整理事件,Dubbo 在接收到事件後,會立即執行服務導出邏輯。整個邏輯大緻可分為三個部分,第一是前置工作,主要用于檢查參數,組裝 URL。第二是導出服務,包含導出服務到本地 (JVM),和導出服務到遠端兩個過程。第三是向注冊中心注冊服務,用于服務發現。

服務引用

在 Dubbo 中,我們可以通過兩種方式引用遠端服務。第一種是使用服務直聯的方式引用服務,第二種方式是基于注冊中心進行引用。

Dubbo 服務引用的時機有兩個,第一個是在 Spring 容器調用 ReferenceBean 的 afterPropertiesSet 方法時引用服務,第二個是在 ReferenceBean 對應的服務被注入到其他類中時引用。這兩個引用服務的時機差別在于,第一個是餓漢式的,第二個是懶漢式的。預設情況下,Dubbo 使用懶漢式引用服務。如果需要使用餓漢式,可通過配置 dubbo:reference 的 init 屬性開啟。下面我們按照 Dubbo 預設配置進行分析,整個分析過程從 ReferenceBean 的 getObject 方法開始。當我們的服務被注入到其他類中時,Spring 會第一時間調用 getObject 方法,并由該方法執行服務引用邏輯。按照慣例,在進行具體工作之前,需先進行配置檢查與收集工作。接着根據收集到的資訊決定服務用的方式,有三種,第一種是引用本地 (JVM) 服務,第二是通過直聯方式引用遠端服務,第三是通過注冊中心引用遠端服務。不管是哪種引用方式,最後都會得到一個 Invoker 執行個體。如果有多個注冊中心,多個服務提供者,這個時候會得到一組 Invoker 執行個體,此時需要通過叢集管理類 Cluster 将多個 Invoker 合并成一個執行個體。合并後的 Invoker 執行個體已經具備調用本地或遠端服務的能力了,但并不能将此執行個體暴露給使用者使用,這會對使用者業務代碼造成侵入。此時架構還需要通過代理工廠類 (ProxyFactory) 為服務接口生成代理類,并讓代理類去調用 Invoker 邏輯。避免了 Dubbo 架構代碼對業務代碼的侵入,同時也讓架構更容易使用。

原文連結

繼續閱讀