1. 程式人生 > 其它 >Dubbo原始碼解析 —— 服務暴露原理

Dubbo原始碼解析 —— 服務暴露原理

前言

之前講完了dubbo叢集容錯系列,現在開始講比較重要的環節,也就是dubbo面試中比較喜歡問的兩個點: 服務釋出服務引用.

插播面試題

  • 服務釋出過程中做了哪些事
  • dubbo都有哪些協議,他們之間有什麼特點,預設值是什麼
  • 什麼是本地暴露和遠端暴露,他們的區別

直入主題

從啟動日誌說起

大家都知道, dubbo是阿里巴巴開源的一個專案,前陣子阿里不僅釋出的程式碼規範手冊,還發布了相應的外掛,從這點我們就知道,阿里是很注重這個程式碼規範的,從 dubbo專案我們也發現了,他有完善的測試體系.說了這麼說,那和我們今天要講的 dubbo的服務釋出有什麼關係呢?當然有,一個規範的專案,必然是有健全的日誌系統.做過其他開發比如iOS開發的都知道,這個控制檯輸出在生產環境是不能隨便輸出的,太多日誌有時候和沒有日誌是一樣的.所以我們來看看這個服務啟動過程中,日誌究竟輸出了什麼.

這裡我用不同顏色的框將關鍵的地方畫了出來,一共有6種顏色,我一次從上到下說一下這釋出過程的一些動作

  • 暴露本地服務
  • 暴露遠端服務
  • 啟動netty
  • 連線zookeeper
  • 到zookeeper註冊
  • 監聽zookeeper

從文件入手,瞭解全域性

經常有人問到,看原始碼要怎麼看.要了解這個服務釋出,文件就是一個很好的切入口,如下

再獻上文件提供的一個時序圖

當然這些都是給已經對原始碼有一定熟悉的人看的,而我的原始碼解析類文件,是給對原始碼不熟悉的人看的.

其實我的每週一更dubbo原始碼系列文章,我的初衷有以下兩個,一個就是做到系統分享,比如dubbo系列文章,我會從不少於 核心, 服務釋出, 服務引用

, 編解碼這四個模組去剖析,後面如果有時間,會臨摹一個簡易的dubbo框架.另一個初衷就是把自己思考的過程和大家分享,在這個分享過程中,其實就是回答了"怎麼看原始碼"這個問題

那麼準備好五菱巨集光,向秋名山出發

出發秋名山

我早年做Android開發的時候,就發現身邊的人都是死在了一個點上,那就是 配置環境.對於看原始碼,很多人最常問的一句話就是,怎麼入手,也就是切入點.那麼我們還是以開頭的日誌為例,來找一個這個切入點

仔細看輸出日誌,就會發現在暴露本地服務之前,有一句很重要的日誌,就是

The service ready on spring started. service: com.alibaba.dubbo.demo.DemoService, dubbo version: <span class="hljs-number">2.0</span>.0, current host: <span class="hljs-number">127.0</span>.0.1

我們利用編譯器的搜尋文字功能,定位到了 ServiceBean這個類,這個類是幹嘛的?好,我假設我也不知道,既然不知道,那我們來看一下他的繼承體系圖

從這個圖我們看到了許多和spring有關的東西,還發現了一個重要的介面,那就是 ApplicationListener.要能敏銳的發現這個關鍵的介面,首先還是要對spring有一定了解,這個就是spring的事件機制(event).什麼是事件機制呢?就比如監聽 spring容器初始化完成.那我們就定位到這行日誌的位置,往下debug

下面要開始敲黑板劃重點了.

從方法名我們很直觀知道目的,但是這裡同事不止一次問過我,這個 dubbo.properties檔案是怎麼時候載入的,好像我根本沒有設定,另外這個 dubbo.properties檔案的名字能不能改?面對這種問題,我從來都是不會直接把答案告訴他,而是告訴他,我是怎麼得到這個答案的,如下圖

同理,對於 log4j.xml這個檔案,好像我從來沒有寫程式碼載入過,為什麼他會載入呢,其實也是同理的

接下來繼續往下走,下面這裡就是我們的第二道面試題

這裡為什麼會進行遍歷呢,因為dubbo是支援多協議的,看文件原話

dubbo支援多種協議,預設使用的是 dubbo協議,具體介紹官方文件寫得很清楚,傳送地址:相關協議介紹

馬不停蹄,下面就到了第三個面試題,也是服務釋出的重點, 本地暴露遠端暴露

為什麼會有 本地暴露遠端暴露呢?不從場景考慮討論技術的沒有意義是.在dubbo中我們一個服務可能既是 Provider,又是 Consumer,因此就存在他自己呼叫自己服務的情況,如果再通過網路去訪問,那自然是捨近求遠,因此他是有 本地暴露服務的這個設計.從這裡我們就知道這個兩者的區別

  • 本地暴露是暴露在JVM中,不需要網路通訊.
  • 遠端暴露是將ip,埠等資訊暴露給遠端客戶端,呼叫時需要網路通訊.

本篇著重講解 服務釋出的整體過程,細節和總結後面會陸續展開.我們忘記下.其實注意一下我這些截圖就能發現,我截的時候會特意把類名和方法名都截出來,方便大家能迅速定位.

從上圖可知,這裡用到了 Adaptive(這個東西非常關鍵,後面會專門一篇講解).點進 ProxyFactory檢視原始碼

@Adaptive註解打在類上和方法上,他們是有區別的(面試也喜歡問這種區別類的問題,這個留在 Adaptive專題說,記得關注肥朝每週一篇原始碼解析 _ ),他打在方法上,就會生成動態編譯的Adaptive類,下面就介紹一下怎麼看這個動態編譯類的原始碼

首先要將這個log4j的level調整為 DEBUG

為什麼需要調整成 DEBUG,更重要的是把如何知道的,告訴大家,比如如下圖,當然這個時候可能會朋友說,我也不知道這個類也還是沒辦法找到這行程式碼.其實這個也是在後面專門的一篇 Adaptive中會說,到時候我會提供另一種實現思路,我們一起思考對比優劣.

開啟 DEBUG後,我們重新啟動,就會看到日誌有如下輸出,這段就是相關程式碼,我們根據包名新建檔案,如下

我們在 getInvoker方法上打上斷點,重啟一下.

由上圖知道,本地暴露的url是以 injvm開頭的,下面來看下遠端暴露,其實這個也是回答 本地暴露遠端暴露區別的一個回答點.面試回答要的並不是一個滿分的答案,而是從一些細節中,看出一個人,是否真的研究過原始碼.

還是回到開頭那句話, dubbo命名是很規範的,從 Wrapper這個命名,其實可以和Spring的 BeanWrapper,以及裝飾者設計模式聯絡起來.同時可以看看文件中的

編碼約定

寫在最後

上面講到了 getInvoker方法,也就是拿到了 Invoker,如果注意到本篇開頭的文件說明中的那句 Dubbo處理服務暴露的關鍵就在Invoker轉換到Exporter的過程,就知道,其實這個 服務暴露還有很多細節是未完待續的,但是由於本篇已有一定篇幅,所以只能下週再見.

如果對你有所幫助,希望點贊,關注支援.鑑於本人才疏學淺,不對的地方還望斧正,也歡迎關注我的簡書,名稱為 肥朝