天天看點

Dubbo 底層原理剖析

閱讀指南

本文會通過 圖文+案例,對 Dubbo 的底層原理進行剖析 - Dubbo 分層的意義。閱讀之前,要求對 Dubbo 有所了解,并且會簡單使用。最好閱讀下前面的一篇文章:基于 Java 實作最初級版的 RPC。

正文

先來看一張摘自官網的 令人頭大 的 Dubbo 架構設計圖,另外還有幾張圖,就不一一貼出了,詳細請參考 Dubbo 架構設計

Dubbo 底層原理剖析

其實 Dubbo 官網關于架構設計的部分已經講得很詳細了,但是對于我們這種沒工作多久的菜鳥,仍然需要花費大量的時間去了解。

架構設計的簡要說明

Dubbo 的架構設計圖中從下至上分為十層,其中,Service 和 Config 層為 API,其它各層均為 SPI。也就是除了 Service 和 Config 層,其餘各層都至少有一種替代品。

比如 Protocol 層:

  • org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol
  • org.apache.dubbo.rpc.protocol.rmi.RmiProtocol
  • org.apache.dubbo.rpc.protocol.http.HttpProtocol

Dubbo 的這種高擴充性全部基于 Dubbo SPI 機制,前面花費了多篇文章去講解 Dubbo SPI 使用,這是研究 Dubbo 源碼的關鍵。

官網 Demo 案例

篇幅原因,具體使用方法和代碼還是到官網 Dubbo - 快速啟動,下面的内容全部基于這個案例。

圖解服務調用過程

官網給出了非常詳細的服務調用過程,都是從架構層面,還有整個流程會經曆哪個類,哪個方法,下面就基于官網的圖文,再結合案例給出自己的了解。

從 main 函數的代碼來看,整個流程看着很簡單
Dubbo 底層原理剖析
當我們加上注冊中心後

結合 xml 配置 和 Dubbo - 架構, 圖解如下:

Dubbo 底層原理剖析
結合架構設計
Dubbo 底層原理剖析

服務引用過程

  • 4.1 Proxy 層

    對服務消費端使用的

    DemoService

    接口進行代理,把本地調用透明地轉換為遠端調用, 該層預設使用的是

    JavassistProxyFactory

    , 對該層的了解,可以參考之前的文章 基于 Java 實作最初級版的 RPC
  • 4.2 Cluster 層

    從圖中可以看出,服務提供者有 2 個執行個體,那麼消費者最終會調用哪個執行個體,就是由 Cluster 層決定的,該層還會橋連注冊中心 zookeeper,擷取 2 個服務提供者的注冊資訊,比如ip,port。當然該層還有其他功能。

  • 4.3 Protocol 層

    要實作圖中的遠端調用,其實本質就是通過網絡通信,來傳輸資訊。Dubbo 為此提供了多種通信協定,預設為 DubboProtocol。

// 有删減
dubbo://LOCALHOST:20880/org.apache.dubbo.demo.DemoService
?anyhost=true&application=demo-provider&bind.ip=192.168.31.87&bind.port=20880&
interface=org.apache.dubbo.demo.DemoService
&methods=sayHello,sayHello1&timestamp=1586693904645
           
  • 4.4 Exchanger 層

    封裝請求響應内容為 Request / Response 對象。做 web 接口開發的都知道,我們會把一些參數或者響應内容封裝到 XXXRequest/YYYResponse 對象中。

  • 4.5 Transport 層

    該層為網絡傳輸層,基于 Netty ,Mina 等通信架構實作。

  • 4.6 Serialize

    既然涉及到網絡傳輸,必然會把請求對象進行序列化操作。

服務暴露過程

  • 5.1 開啟 Server 并監聽指定端口
  • 5.2 将請求資料進行反序列化
  • 5.3 Exchanger 負責解析 Request 對象
  • 5.4 通過 Protocol 層, 根據具體協定解析 Request 對象
  • 5.5 對服務提供者的服務實作類進行代理

總結

本文結合官網的 Demo 案例, 通過畫圖的方式, 對 Dubbo 的架構設計圖進行了簡化, 目的是了解 Dubbo 架構分層的作用。一個簡單的 RPC 就是基于動态代理 + 網絡通信,

  • 動态代理 (Proxy) 就是把本地調用透明轉換為遠端調用
  • 遠端調用就要涉及到網絡通信 (Transport) - 基于 socket
  • 在 socket 基礎上, 我們可以自定義我們的協定 (Protocol) ,也可以複用現有的協定,比如 http
  • 基于上面的過程, 我們可以封裝 Request / Response 對象 (Exchanger)
  • 既然要網絡傳輸, 就要想辦法進行序列化/反序列化 (Serialize)
  • 當提供多個服務提供者執行個體時, 就應該有一個地方 (注冊中心 Register) 負責管理服務提供者的中繼資料資訊,
  • 當消費者從上面的多個服務提供者 選取一個 調用服務 (Cluster) 時, 就要選取某種政策 (比如輪詢, hash)
  • 最後需要一個監控中心 (Monitor) , 負責一些統計功能,比如服務調用次數

繼續閱讀