作者:肥朝
原文地址:http://www.jianshu.com/p/893f7e6e0c58
友情提示:歡迎關註公眾號【芋道原始碼】。?關註後,拉你進【原始碼圈】微信群和【肥朝】搞基嗨皮。
友情提示:歡迎關註公眾號【芋道原始碼】。?關註後,拉你進【原始碼圈】微信群和【肥朝】搞基嗨皮。
友情提示:歡迎關註公眾號【芋道原始碼】。?關註後,拉你進【原始碼圈】微信群和【肥朝】搞基嗨皮。
前言
本篇講的是dubbo中比較重要的 遠端暴露
,鑒於上一篇dubbo原始碼解析-本地暴露採用一圖勝千言的寫法好像讀者並不太容易理解,加上之前寫的別怕看原始碼,一張圖搞定Mybatis的Mapper原理中的讀者評論中看出,這種方式可能有點粗暴.這個後面有時間會補上一些更細緻的文字說明
自從每週一更以來,也有不少朋友問到我 怎麼看原始碼
這個問題.鑒於高中老師告訴我,作文怕走題的話,就要時刻點題.這種點題的思想也一直延續到現在,所以我的原始碼解析系列,也幾乎都把自己分析的思路暴露出來,其實也是時刻在回答這個 怎麼看原始碼
的問題.
昨天下午一個好朋友也打電話給我,說他去面試(廣州)問到了 從看原始碼中你學到了什麼?
這個問題.其實能學到的東西就太多了.比如你看任何一個框架的原始碼,那麼首先要看一下 設計樣式
吧,任何一個成熟的框架少不了工廠樣式.再具體一點,看 dubbo原始碼
,你就要順便學一下 zookeeper
, netty
, spring事件機制
的一些簡單知識.像 SPI
, javassist
這些知識你工作了幾年可能還沒用過吧.同時我們根據這些再深入思考一下,比如dubbo中拼接生成動態編譯類的做法,我們可不可以用其他方式來實現呢?比如透過 freemarker
這樣的模板引擎.既然能生成動態編譯類,那像CRUD這種比較固定的程式碼,我們是不是又可以用這個模板引擎做一個 程式碼生成器
呢?
言歸正傳,我們回到主題.鑒於前面提到的點題思想,就那以本篇為例,時刻提一下 從原始碼中你學到了什麼
插播面試題
-
服務暴露中遠端暴露的總體過程,畫圖和文字方式說明
預熱概念
首先上一張dubbo文章中非常經典的一張圖
相信大家初學dubbo的時候都看過這張圖,但是可能當時沒理解這個圖究竟想說的是什麼.圖中圈出來的部分就是今天要講的 遠端暴露
,當然我還會做一些補充.
為什麼這次我不直接自己畫圖,而是取用官方檔案的圖?原因很簡單,因為假如我直接把圖畫出來,就是相當把這些概念填鴨式的告訴你,這樣你無法看到我的思考過程,也就是說,我並沒有告訴大家,這些東西我是怎麼知道的,然而這一點,才是原始碼解析類文章,最應該表達的思想.所以我每篇文章都先從檔案入手,以dubug程式碼的方式驗證,這就是我的思考過程,也是我看原始碼的過程(粗暴式點題怎麼看原始碼).當然後面視情況也會補上一些個人自己花的圖加以總結.
另外註意的是,圖中的箭頭方向是從 Consumer
到 Provider
的過程,所以這個暴露的過程,是我紅框出來的反方向
直入主題
由於前兩篇dubbo原始碼解析-服務暴露原理和dubbo原始碼解析-本地暴露已經多次講述了 getInvoker
的過程,遠端暴露也大同小異,所以不再細述.直接從 protocol.export(invoker)
開始,另外每個截圖我都會儘量把類名和方法名截圖出來,方便讀者一起debug,另外這些動態編譯類(黃色圈出來的)除錯方式請參考 服務暴露原理
這篇
由經典的互動圖知道,下一個關鍵詞是 Filter
,由於這個也和前面講得大同小異,所以就將過程簡單瀏覽回顧一下
下麵我們似乎又看到了一位熟悉的老朋友,在 本地暴露
中我們也看過這行程式碼,為何 本地暴露
和 遠端暴露
中都有他的身影?歡迎簡書關註肥朝,在 服務取用
那一節我們再揭秘
同時我們已經到了第三個關鍵詞 Procotol
,老規矩,我們來看看他的繼承體系圖(粗暴式點題,怎麼看原始碼)
那這種繼承體繫有什麼好處呢?要想說明一個程式碼好,那就必須拿個比較一般程式碼來對比了.由於篇幅有限,推薦看 大話設計樣式
的第一章,該章用一個計算器的例子,將一個比較一般的程式碼一步一步演進成類似結構(粗暴式點題,從看原始碼中學到了什麼).
按照經典圖的路線,我們下一個關鍵詞應該就是 Server
了,從方法名 openServer(url)
也可以看出來確實是這樣.當然我在 預熱概念
中也提到,我會做一些補充,那麼我要在這個 Procotol
和 Transporter
插播一個關鍵詞,那就是 Exchanger
從單詞意思我們知道,這個是 交換
的意思,按照計算機術語,這個稱之為 交換層
更貼切.那麼問題來了,他交換什麼東西?那我們來看一下他的方法圖(粗暴式點題,怎麼看原始碼)
我們捕捉到了幾個關鍵詞, Client
, Server
,其實這個交換層,就是做 封裝請求與響應
之間的互動層.那麼為什麼需要這麼個互動層呢?這麼設計有什麼好處呢?好,那我們開啟 阿裡巴巴Java開發手冊
我來舉個例子, java web
中傳統的請求響應方式都是 controller->service->dao
,然後 dao->service->controller
,從手冊我們知道,從 dao
傳出來的是 DO
,但是 controller
需要的是 VO
,那麼我們是不是需要一個中間的互動層來做這些轉換?這個例子雖然不足以描述這種設計的好,但是比較可能比較好理解一些.(粗暴式點題,看原始碼學到了什麼)
那我們繼續往下走
下麵就要註意了,我們要來到下一個關鍵詞 Transporter
,這個從字面理解為 傳輸層
,那這個究竟是什麼傳輸層?我們來看一下繼承體系圖(粗暴式點題,怎麼看原始碼)
從這裡就可以看出,這個是 網路傳輸層
,其中 Grizzly
和 Mina
和 Netty
都是非常有名的NIO框架,想瞭解他們可以查一下相關資料(粗暴式點題,看原始碼學到了什麼)
繼續往下走,看到這裡有個構造方法,那麼就要敲黑板畫一下重點了.看原始碼凡是遇到構造方法的,都要特別註意,因為我們知道呼叫構造方法前,會先呼叫父類的構造方法,因此,這個繼承體系圖是要看一下的(粗暴式點題,怎麼看原始碼)
因此我們將斷點打到他的父類上,可以看出,這做的主要是一些根據配置檔案設定一些超時時間之類的
高潮還沒完,我們註意到,在 AbstractServer
類中有一個 doOpen()
方法.這個 doOpen()
方法方法是一個抽象方法,這種做法稱之為 鉤子方法
.也叫 模板方法
,熟悉設計樣式的話,會對這種方式並不樣式,其實在 Servlet
的 init()
方法也是這種做法,可以看看 Servlet
的原始碼(粗暴式點題,看原始碼學到了什麼)
那麼我們就到了 doOpen
方法,這裡如果大家寫過一些簡單的netty例子看到這段程式碼就會很熟悉了
另外提一下這個 9
並不是固定的,這個和我們的機器是有關的,不熟悉的引數我們可以用以下的方式查一下檔案(粗暴式點題,怎麼看原始碼)
那麼繼續走,這裡為什麼會進入這個構造方法呢?註意我們在提 Transporter
關鍵詞之前是有 new
一個 HeaderExchangeServer
物件的.在這個構造方法中,透過 startHeatbeatTimer
設定了netty的心跳,這些netty的細節我們在後面的netty專題再細說
正如官方檔案所說 Dubbo處理服務暴露的關鍵就在Invoker轉換到Exporter的過程
,看到這個 exporter
,也預告本篇走到了尾聲
寫在末尾
本篇中比較粗暴的多次進行 怎麼看原始碼
和 看原始碼學到了什麼
的點題,讓我彷彿回到了高中寫作業的時光.當然這種方式也只是肥朝個人的拙見,並不是看原始碼的最佳實踐.有好的想法也歡迎和我交流,我們下週見.鑒於本人才疏學淺,不對的地方還望斧正,也歡迎點贊或者關註我的簡書,名稱為 肥朝