從0開始學微服務:10 Dubbo框架裡的微服務組件

從0開始學微服務:10 Dubbo框架裡的微服務組件

經過前面幾期的講解,你應該已經對微服務的架構有了初步的瞭解。簡單回顧一下,微服務的架構主要包括服務描述、服務發現、服務調用、服務監控、服務追蹤以及服務治理這幾個基本組件。

那麼每個基本組件從架構和代碼設計上該如何實現?組件之間又是如何串聯來實現一個完整的微服務架構呢?今天我就以開源微服務框架 Dubbo 為例來給你具體講解這些組件。

服務發佈與引用

專欄前面我講過服務發佈與引用的三種常用方式:RESTful API、XML 配置以及 IDL 文件,其中 Dubbo 框架主要是使用 XML 配置方式,接下來我通過具體實例,來給你講講 Dubbo 框架服務發佈與引用是如何實現的。

首先來看服務發佈的過程,下面這段代碼是服務提供者的 XML 配置。


<beans> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

<application>

<registry>

<protocol>

<service>

<bean>
/<beans>

其中“dubbo:service”開頭的配置項聲明瞭服務提供者要發佈的接口,“dubbo:protocol”開頭的配置項聲明瞭服務提供者要發佈的接口的協議以及端口號。

Dubbo 會把以上配置項解析成下面的 URL 格式:

dubbo://host-ip:20880/com.alibaba.dubbo.demo.DemoService

然後基於擴展點自適應機制,通過 URL 的“dubbo://”協議頭識別,就會調用 DubboProtocol 的 export() 方法,打開服務端口 20880,就可以把服務 demoService 暴露到 20880 端口了。

再來看下服務引用的過程,下面這段代碼是服務消費者的 XML 配置。


<beans> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

<application>

<registry>

<reference>
/<beans>

其中“dubbo:reference”開頭的配置項聲明瞭服務消費者要引用的服務,Dubbo 會把以上配置項解析成下面的 URL 格式:

dubbo://com.alibaba.dubbo.demo.DemoService

然後基於擴展點自適應機制,通過 URL 的“dubbo://”協議頭識別,就會調用 DubboProtocol 的 refer() 方法,得到服務 demoService 引用,完成服務引用過程。

服務註冊與發現

先來看下服務提供者註冊服務的過程,繼續以前面服務提供者的 XML 配置為例,其中“dubbo://registry”開頭的配置項聲明瞭註冊中心的地址,Dubbo 會把以上配置項解析成下面的 URL 格式:

registry://multicast://224.5.6.7:1234/com.alibaba.dubbo.registry.RegistryService?export=URL.encode("dubbo://host-ip:20880/com.alibaba.dubbo.demo.DemoService")

然後基於擴展點自適應機制,通過 URL 的“registry://”協議頭識別,就會調用 RegistryProtocol 的 export() 方法,將 export 參數中的提供者 URL,註冊到註冊中心。

再來看下服務消費者發現服務的過程,同樣以前面服務消費者的 XML 配置為例,其中“dubbo://registry”開頭的配置項聲明瞭註冊中心的地址,跟服務註冊的原理類似,Dubbo 也會把以上配置項解析成下面的 URL 格式:

registry://multicast://224.5.6.7:1234/com.alibaba.dubbo.registry.RegistryService?refer=URL.encode("consummer://host-ip/com.alibaba.dubbo.demo.DemoService")

然後基於擴展點自適應機制,通過 URL 的“registry://”協議頭識別,就會調用 RegistryProtocol 的 refer() 方法,基於 refer 參數中的條件,查詢服務 demoService 的地址。

服務調用

專欄前面我講過在服務調用的過程中,通常把服務消費者叫作客戶端,服務提供者叫作服務端,發起一次服務調用需要解決四個問題:

  • 客戶端和服務端如何建立網絡連接?
  • 服務端如何處理請求?
  • 數據傳輸採用什麼協議?
  • 數據該如何序列化和反序列化?

其中前兩個問題客戶端和服務端如何建立連接和服務端如何處理請求是通信框架要解決的問題,Dubbo 支持多種通信框架,比如 Netty 4,需要在服務端和客戶端的 XML 配置中添加下面的配置項。

服務端:

<protocol>

客戶端:

<consumer>

這樣基於擴展點自適應機制,客戶端和服務端之間的調用會通過 Netty 4 框架來建立連接,並且服務端採用 NIO 方式來處理客戶端的請求。

再來看下 Dubbo 的數據傳輸採用什麼協議。Dubbo 不僅支持私有的 Dubbo 協議,還支持其他協議比如 Hessian、RMI、HTTP、Web Service、Thrift 等。下面這張圖描述了私有 Dubbo 協議的協議頭約定。

從0開始學微服務:10 Dubbo框架裡的微服務組件

至於數據序列化和反序列方面,Dubbo 同樣也支持多種序列化格式,比如 Dubbo、Hession 2.0、JSON、Java、Kryo 以及 FST 等,可以通過在 XML 配置中添加下面的配置項。

例如:

<protocol>

服務監控

服務監控主要包括四個流程:數據採集、數據傳輸、數據處理和數據展示,其中服務框架的作用是進行埋點數據採集,然後上報給監控系統。

在 Dubbo 框架中,無論是服務提供者還是服務消費者,在執行服務調用的時候,都會經過 Filter 調用鏈攔截,來完成一些特定功能,比如監控數據埋點就是通過在 Filter 調用鏈上裝備了 MonitorFilter 來實現的,詳細的代碼實現你可以參考這裡。

服務治理

服務治理手段包括節點管理、負載均衡、服務路由、服務容錯等,下面這張圖給出了 Dubbo 框架服務治理的具體實現。

從0開始學微服務:10 Dubbo框架裡的微服務組件

圖中的 Invoker 是對服務提供者節點的抽象,Invoker 封裝了服務提供者的地址以及接口信息。

  • 節點管理:Directory 負責從註冊中心獲取服務節點列表,並封裝成多個 Invoker,可以把它看成“List<invoker>” ,它的值可能是動態變化的,比如註冊中心推送變更時需要更新。/<invoker>
  • 負載均衡:LoadBalance 負責從多個 Invoker 中選出某一個用於發起調用,選擇時可以採用多種負載均衡算法,比如 Random、RoundRobin、LeastActive 等。
  • 服務路由:Router 負責從多個 Invoker 中按路由規則選出子集,比如讀寫分離、機房隔離等。
  • 服務容錯:Cluster 將 Directory 中的多個 Invoker 偽裝成一個 Invoker,對上層透明,偽裝過程包含了容錯邏輯,比如採用 Failover 策略的話,調用失敗後,會選擇另一個 Invoker,重試請求。

一次服務調用的流程

上面我講的是 Dubbo 下每個基本組件的實現方式,那麼 Dubbo 框架下,一次服務調用的流程是什麼樣的呢?下面結合這張圖,我來給你詳細講解一下。

從0開始學微服務:10 Dubbo框架裡的微服務組件

首先我來解釋微服務架構中各個組件分別對應到上面這張圖中是如何實現。

  • 服務發佈與引用:對應實現是圖裡的 Proxy 服務代理層,Proxy 根據客戶端和服務端的接口描述,生成接口對應的客戶端和服務端的 Stub,使得客戶端調用服務端就像本地調用一樣。
  • 服務註冊與發現:對應實現是圖裡的 Registry 註冊中心層,Registry 根據客戶端和服務端的接口描述,解析成服務的 URL 格式,然後調用註冊中心的 API,完成服務的註冊和發現。
  • 服務調用:對應實現是 Protocol 遠程調用層,Protocol 把客戶端的本地請求轉換成 RPC 請求。然後通過 Transporter 層來實現通信,Codec 層來實現協議封裝,Serialization 層來實現數據序列化和反序列化。
  • 服務監控:對應實現層是 Filter 調用鏈層,通過在 Filter 調用鏈層中加入 MonitorFilter,實現對每一次調用的攔截,在調用前後進行埋點數據採集,上傳給監控系統。
  • 服務治理:對應實現層是 Cluster 層,負責服務節點管理、負載均衡、服務路由以及服務容錯。

再來看下微服務架構各個組件是如何串聯起來組成一個完整的微服務框架的,以 Dubbo 框架下一次服務調用的過程為例,先來看下客戶端發起調用的過程。

  • 首先根據接口定義,通過 Proxy 層封裝好的透明化接口代理,發起調用。
  • 然後在通過 Registry 層封裝好的服務發現功能,獲取所有可用的服務提供者節點列表。
  • 再根據 Cluster 層的負載均衡算法從可用的服務節點列表中選取一個節點發起服務調用,如果調用失敗,根據 Cluster 層提供的服務容錯手段進行處理。
  • 同時通過 Filter 層攔截調用,實現客戶端的監控統計。
  • 最後在 Protocol 層,封裝成 Dubbo RPC 請求,發給服務端節點。

這樣的話,客戶端的請求就從一個本地調用轉化成一個遠程 RPC 調用,經過服務調用框架的處理,通過網絡傳輸到達服務端。其中服務調用框架包括通信協框架 Transporter、通信協議 Codec、序列化 Serialization 三層處理。

服務端從網絡中接收到請求後的處理過程是這樣的:

  • 首先在 Protocol 層,把網絡上的請求解析成 Dubbo RPC 請求。
  • 然後通過 Filter 攔截調用,實現服務端的監控統計。
  • 最後通過 Proxy 層的處理,把 Dubbo RPC 請求轉化為接口的具體實現,執行調用。

總結

今天我給你講述了 Dubbo 服務化框架每個基本組件的實現方式,以及一次 Dubbo 調用的流程。

對於學習微服務架構來說,最好的方式是去實際搭建一個微服務的框架,甚至去從代碼入手做一些二次開發。

你可以按照 Dubbo 的官方文檔去安裝並搭建一個服務化框架。如果想深入瞭解它的實現的話,可以下載源碼來閱讀。

思考題

在以 Dubbo 為例,學習完服務化框架的具體實現後,你對其中的實現細節還有什麼疑問嗎?

歡迎你在留言區寫下自己的思考,與我一起討論。


分享到:


相關文章: