1. 程式人生 > 其它 >Dubbo系列-Dubbo常見面試題

Dubbo系列-Dubbo常見面試題

開始你的表演:


知道什麼是 RPC 麼?

  一般面試官會以這樣的問題來切入、熱場,畢面試也是循序漸進的過程,所以你也不用太心急一開始就芭芭拉說一堆,要抓住關鍵點簡單闡述先。

  而且面試官能從這個問題鑑定出你平日的工作內容會不會連 RPC 都沒接觸過,會不會就只是一條龍的 Spring MVC ?

  確實有很多同學沒接觸過 RPC ,也很正常比如一些外包或者一些小專案都接觸不到的,不過平日接觸不到和你不知道這個東西是兩個概念。

  能從側面反映出這個人工作之餘應該不怎麼學習,連 RPC 都不知道,所以怎麼都說不過去,基本上要涼涼,對你的初始印象就差了,除非你能從後面有亮眼的表現。

答:RPC 就是 Remote Procedure Call,遠端過程呼叫,它相對應的是本地過程呼叫。

那為什麼要有 RPC,HTTP 不好麼?

  這時候面試官就開始追問了。

  這個問題其實很有意思,有些面試官可能自己不太清楚,然後以為自己很清楚,所以問出這個問題,還有一種是真的清楚,問這個問題是為了讓你跳坑裡。

  因為 RPC 和 HTTP 就不是一個層級的東西,所以嚴格意義上這兩個沒有可比性,也不應該來作比較,而題目問的就是把這兩個作為比較了。

  HTTP 只是傳輸協議,協議只是規範了一定的交流格式,而且 RPC 是早於 HTTP 的,所以真要問也是問有 RPC 為什麼還要 HTTP。

  RPC 對比的是本地過程呼叫,是用來作為分散式系統之間的通訊,它可以用 HTTP 來傳輸,也可以基於 TCP 自定義協議傳輸。

所以你要先提出這兩個不是一個層級的東西,沒有可比性,然後再表現一下,可以說 HTTP 協議比較冗餘,所以 RPC 大多都是基於 TCP 自定義協議,定製化的才是最適合自己的。

當然也有基於 HTTP 協議的 RPC 框架,畢竟 HTTP 是公開的協議,比較通用,像 HTTP2 已經做了相應的壓縮了,而且系統之間的呼叫都在內網,所以說影響也不會很大。


這波回答下來,面試官會覺得你有點東西,開始對你有點興趣了,要開始深入你了。

看過原始碼,那說下服務暴露的流程?

  服務的暴露起始於 Spring IOC 容器重新整理完畢之後,會根據配置引數組裝成 URL, 然後根據 URL 的引數來進行本地或者遠端呼叫。

  會通過 proxyFactory.getInvoker,利用 javassist 來進行動態代理,封裝真的實現類,然後再通過 URL 引數選擇對應的協議來進行 protocol.export,預設是 Dubbo 協議。

  在第一次暴露的時候會呼叫 createServer 來建立 Server,預設是 NettyServer。

  然後將 export 得到的 exporter 存入一個 Map 中,供之後的遠端呼叫查詢,然後會向註冊中心註冊提供者的資訊。

基本上就是這麼個流程,說了這些差不多了,太細的誰都記住不。

看過原始碼,那說下服務引入的流程?

  服務的引入時機有兩種,第一種是 餓漢式,第二種是 懶漢式

  餓漢式就是載入完畢就會引入,懶漢式是隻有當這個服務被注入到其他類中時啟動引入流程,預設是 懶漢式

  會先根據配置引數組裝成 URL ,一般而言我們都會配置的註冊中心,所以會構建 RegistryDirectory 向註冊中心註冊消費者的資訊,並且訂閱提供者、配置、路由等節點。

  得知提供者的資訊之後會進入 Dubbo 協議的引入,會建立 Invoker ,期間會包含 NettyClient,來進行遠端通訊,最後通過 Cluster 來包裝 Invoker,預設是 FailoverCluster,最終返回代理類。

說這麼多差不多了,關鍵的點都提到了。

  切忌不要太過細,不要把你知道的都說了,這樣會抓不住重點,比如上面的流程你要插入,引入的三種方式:本地引入、直連遠端引入、通過註冊中心引入。

  然後再分別說本地引入怎樣的,芭芭拉的就會很亂,所以面試的時候是需要刪減的,要直擊重點。

  其實真實說的應該比我上面說的還要精簡點才行,我是怕大家不太清楚說的稍微詳細了一些。

看過原始碼,那說下服務呼叫的流程?

  呼叫某個介面的方法會呼叫之前生成的代理類,然後會從 cluster 中經過路由的過濾、負載均衡機制選擇一個 invoker 發起遠端呼叫,此時會記錄此請求和請求的 ID 等待服務端的響應。

  服務端接受請求之後會通過引數找到之前暴露儲存的 map,得到相應的 exporter ,然後最終呼叫真正的實現類,再組裝好結果返回,這個響應會帶上之前請求的 ID。

  消費者收到這個響應之後會通過 ID 去找之前記錄的請求,然後找到請求之後將響應塞到對應的 Future 中,喚醒等待的執行緒,最後消費者得到響應,一個流程完畢。

關鍵的就是 cluster、路由、負載均衡,然後 Dubbo 預設是非同步的,所以請求和響應是如何對應上的。

知道什麼是 SPI 嘛?

  這又是一個方向了,從上面的回答中,不論是從 Dubbo 協議,還是 cluster ,什麼 export 方法等等無處不是 SPI 的影子,

所以如果是問 Dubbo 方面的問題,問 SPI 是毋庸置疑的,因為原始碼裡 SPI 無處不在,而且 SPI 也是 Dubbo 可擴充套件性的基石。

所以這個題目沒什麼套路,直接答就行。

  SPI 是 Service Provider Interface,主要用於框架中,框架定義好介面,不同的使用者有不同的需求,因此需要有不同的實現,而 SPI 就通過定義一個特定的位置,

Java SPI 約定在 Classpath 下的 META-INF/services/ 目錄裡建立一個以服務介面命名的檔案,然後檔案裡面記錄的是此 jar 包提供的具體實現類的全限定名。

所以就可以通過介面找到對應的檔案,獲取具體的實現類然後載入即可,做到了靈活的替換具體的實現類。

為什麼 Dubbo 不用 JDK 的 SPI,而是要自己實現?

  問這個問題就是看你有沒有深入的瞭解,或者自己思考過,不是死板的看原始碼,或者看一些知識點。

  很多點是要思考的,不是書上說什麼就是什麼,你要知道這樣做的理由,有什麼好處和壞處,這很容易看出一個人是死記硬背還是有自己的思考。

答:因為 Java SPI 在查詢擴充套件實現類的時候遍歷 SPI 的配置檔案並且將實現類全部例項化,假設一個實現類初始化過程比較消耗資源且耗時,但是你的程式碼裡面又用不上它,

這就產生了資源的浪費。

因此 Dubbo 就自己實現了一個 SPI,給每個實現類配了個名字,通過名字去檔案裡面找到對應的實現類全限定名然後載入例項化,按需載入。

這答出來就加分了,面試官心裡在拍手了,不錯不錯有點東西。

Dubbo 為什麼預設用 Javassist ?

  上面你回答 Dubbo 用 Javassist 動態代理,所以很可能會問你為什麼要用這個代理,可能還會引申出 JDK 的動態代理、ASM、CGLIB。

  所以這也是個注意點,如果你不太清楚的話上面的回答就不要扯到動態代理了,如果清楚的話那肯定得提,來誘導面試官來問你動態代理方面的問題,這很關鍵。

  面試官是需要誘導的,畢竟他也想知道你優秀的方面到底有多優秀,你也取長補短,雙贏雙贏。

  來回答下為什麼用 Javassist,很簡單,就是快,且位元組碼生成方便。

  ASM 比 Javassist 更快,但是沒有快一個數量級,而Javassist 只需用字串拼接就可以生成位元組碼,而 ASM 需要手工生成,成本較高,比較麻煩