歡迎光臨
每天分享高質量文章

Dubbo原始碼解析 – 遠程暴露

作者:肥朝
原文地址:http://www.jianshu.com/p/893f7e6e0c58

友情提示:歡迎關註公眾號【芋道原始碼】。?關註後,拉你進【原始碼圈】微信群和【肥朝】搞基嗨皮。

友情提示:歡迎關註公眾號【芋道原始碼】。?關註後,拉你進【原始碼圈】微信群和【肥朝】搞基嗨皮。

友情提示:歡迎關註公眾號【芋道原始碼】。?關註後,拉你進【原始碼圈】微信群和【肥朝】搞基嗨皮。

前言

本篇講的是dubbo中比較重要的 遠程暴露,鑒於上一篇dubbo原始碼解析-本地暴露採用一圖勝千言的寫法好像讀者並不太容易理解,加上之前寫的別怕看原始碼,一張圖搞定Mybatis的Mapper原理中的讀者評論中看出,這種方式可能有點粗暴.這個後面有時間會補上一些更細緻的文字說明

自從每周一更以來,也有不少朋友問到我 怎麼看原始碼這個問題.鑒於高中老師告訴我,作文怕走題的話,就要時刻點題.這種點題的思想也一直延續到現在,所以我的原始碼解析系列,也幾乎都把自己分析的思路暴露出來,其實也是時刻在回答這個 怎麼看原始碼的問題.

昨天下午一個好朋友也打電話給我,說他去面試(廣州)問到了 從看原始碼中你學到了什麼?這個問題.其實能學到的東西就太多了.比如你看任何一個框架的原始碼,那麼首先要看一下 設計樣式吧,任何一個成熟的框架少不了工廠樣式.再具體一點,看 dubbo原始碼,你就要順便學一下 zookeeper, netty, spring事件機制的一些簡單知識.像 SPI, javassist這些知識你工作了幾年可能還沒用過吧.同時我們根據這些再深入思考一下,比如dubbo中拼接生成動態編譯類的做法,我們可不可以用其他方式來實現呢?比如通過 freemarker這樣的模板引擎.既然能生成動態編譯類,那像CRUD這種比較固定的代碼,我們是不是又可以用這個模板引擎做一個 代碼生成器呢?

言歸正傳,我們回到主題.鑒於前面提到的點題思想,就那以本篇為例,時刻提一下 從原始碼中你學到了什麼

插播面試題

  • 服務暴露中遠程暴露的總體過程,畫圖和文字方式說明

預熱概念

首先上一張dubbo文章中非常經典的一張圖

相信大家初學dubbo的時候都看過這張圖,但是可能當時沒理解這個圖究竟想說的是什麼.圖中圈出來的部分就是今天要講的 遠程暴露,當然我還會做一些補充.

為什麼這次我不直接自己畫圖,而是取用官方文件的圖?原因很簡單,因為假如我直接把圖畫出來,就是相當把這些概念填鴨式的告訴你,這樣你無法看到我的思考過程,也就是說,我並沒有告訴大家,這些東西我是怎麼知道的,然而這一點,才是原始碼解析類文章,最應該表達的思想.所以我每篇文章都先從文件入手,以dubug代碼的方式驗證,這就是我的思考過程,也是我看原始碼的過程(粗暴式點題怎麼看原始碼).當然後面視情況也會補上一些個人自己花的圖加以總結.

另外註意的是,圖中的箭頭方向是從 ConsumerProvider的過程,所以這個暴露的過程,是我紅框出來的反方向

直入主題

由於前兩篇dubbo原始碼解析-服務暴露原理和dubbo原始碼解析-本地暴露已經多次講述了 getInvoker的過程,遠程暴露也大同小異,所以不再細述.直接從 protocol.export(invoker)開始,另外每個截圖我都會儘量把類名和方法名截圖出來,方便讀者一起debug,另外這些動態編譯類(黃色圈出來的)除錯方式請參考 服務暴露原理這篇

由經典的交互圖知道,下一個關鍵詞是 Filter,由於這個也和前面講得大同小異,所以就將過程簡單瀏覽回顧一下

下麵我們似乎又看到了一位熟悉的老朋友,在 本地暴露中我們也看過這行代碼,為何 本地暴露遠程暴露中都有他的身影?歡迎簡書關註肥朝,在 服務取用那一節我們再揭秘

同時我們已經到了第三個關鍵詞 Procotol,老規矩,我們來看看他的繼承體系圖(粗暴式點題,怎麼看原始碼)

那這種繼承體系有什麼好處呢?要想說明一個代碼好,那就必須拿個比較一般代碼來對比了.由於篇幅有限,推薦看 大話設計樣式的第一章,該章用一個計算器的例子,將一個比較一般的代碼一步一步演進成類似結構(粗暴式點題,從看原始碼中學到了什麼).

按照經典圖的路線,我們下一個關鍵詞應該就是 Server了,從方法名 openServer(url)也可以看出來確實是這樣.當然我在 預熱概念中也提到,我會做一些補充,那麼我要在這個 ProcotolTransporter插播一個關鍵詞,那就是 Exchanger

從單詞意思我們知道,這個是 交換的意思,按照計算機術語,這個稱之為 交換層更貼切.那麼問題來了,他交換什麼東西?那我們來看一下他的方法圖(粗暴式點題,怎麼看原始碼)

我們捕捉到了幾個關鍵詞, Client, Server,其實這個交換層,就是做 封裝請求與響應之間的交互層.那麼為什麼需要這麼個交互層呢?這麼設計有什麼好處呢?好,那我們打開 阿裡巴巴Java開發手冊

我來舉個例子, java web中傳統的請求響應方式都是 controller->service->dao,然後 dao->service->controller,從手冊我們知道,從 dao傳出來的是 DO,但是 controller需要的是 VO,那麼我們是不是需要一個中間的交互層來做這些轉換?這個例子雖然不足以描述這種設計的好,但是比較可能比較好理解一些.(粗暴式點題,看原始碼學到了什麼)

那我們繼續往下走

下麵就要註意了,我們要來到下一個關鍵詞 Transporter,這個從字面理解為 傳輸層,那這個究竟是什麼傳輸層?我們來看一下繼承體系圖(粗暴式點題,怎麼看原始碼)

從這裡就可以看出,這個是 網絡傳輸層,其中 GrizzlyMinaNetty都是非常有名的NIO框架,想瞭解他們可以查一下相關資料(粗暴式點題,看原始碼學到了什麼)

繼續往下走,看到這裡有個構造方法,那麼就要敲黑板畫一下重點了.看原始碼凡是遇到構造方法的,都要特別註意,因為我們知道呼叫構造方法前,會先呼叫父類的構造方法,因此,這個繼承體系圖是要看一下的(粗暴式點題,怎麼看原始碼)

因此我們將斷點打到他的父類上,可以看出,這做的主要是一些根據配置檔案設置一些超時時間之類的

高潮還沒完,我們註意到,在 AbstractServer類中有一個 doOpen()方法.這個 doOpen()方法方法是一個抽象方法,這種做法稱之為 鉤子方法.也叫 模板方法,熟悉設計樣式的話,會對這種方式並不樣式,其實在 Servletinit()方法也是這種做法,可以看看 Servlet的原始碼(粗暴式點題,看原始碼學到了什麼)

那麼我們就到了 doOpen方法,這裡如果大家寫過一些簡單的netty例子看到這段代碼就會很熟悉了

另外提一下這個 9並不是固定的,這個和我們的機器是有關的,不熟悉的引數我們可以用以下的方式查一下文件(粗暴式點題,怎麼看原始碼)

那麼繼續走,這裡為什麼會進入這個構造方法呢?註意我們在提 Transporter關鍵詞之前是有 new一個 HeaderExchangeServer物件的.在這個構造方法中,通過 startHeatbeatTimer設置了netty的心跳,這些netty的細節我們在後面的netty專題再細說

正如官方文件所說 Dubbo處理服務暴露的關鍵就在Invoker轉換到Exporter的過程,看到這個 exporter,也預告本篇走到了尾聲

寫在末尾

本篇中比較粗暴的多次進行 怎麼看原始碼看原始碼學到了什麼的點題,讓我仿佛回到了高中寫作業的時光.當然這種方式也只是肥朝個人的拙見,並不是看原始碼的最佳實踐.有好的想法也歡迎和我交流,我們下周見.鑒於本人才疏學淺,不對的地方還望斧正,也歡迎點贊或者關註我的簡書,名稱為 肥朝

赞(0)

分享創造快樂