java開發分佈式服務框架Dubbo原理機制詳解

前言

在介紹Dubbo之前先瞭解一下基本概念:

Dubbo是一個RPC框架,RPC,即Remote Procedure Call(遠程過程調用),相對的就是本地過程調用,在分佈式架構之前的單體應用架構和垂直應用架構運用的都是本地過程調用。它允許程序調用另外一個地址空間(通常是網絡共享的另外一臺機器)的過程或函數,並且不用程序員顯式編碼這個遠程調用的細節。

而分佈式架構應用與應用之間的遠程調用就需要RPC框架來做,目的就是為瞭讓遠程調用像本地調用一樣簡單。

在這裡插入圖片描述

Dubbo框架有以下部件

Consumer

即調用遠程服務的服務消費方,消費者需要面向接口編程,知道瞭哪些接口可以調用瞭,具體實現需要框架提供一個代理類來為接口提供具體實現,讓消費者隻管調用什麼接口,而具體實現的獲取由代理類來處理。

消費者還需要提供調用方法名以及方法的參數值。

但是代理類此時還不知道需要調用哪個服務器上的遠程方法,此時需要一個註冊中心,通過註冊中心獲取可以調用的遠程服務列表。

遠程服務器一般都是集群部署,那麼調用哪個服務器則需要通過負載均衡來選擇一個最合適的服務器來調用。

同時還需要有集群容錯機制,因為各種原因,可能遠程調用會失敗,此時需要容錯機制來重試調用,保證遠程調用的穩定性。

同時與服務提供方約定好通信協議和序列化格式,方便通信以及數據傳輸。

Provider

即暴露服務的服務提供方,服務提供方內部實現具體的接口,然後將接口暴露出去,再將服務註冊到註冊中心,服務消費方調用服務,提供者接收到調用請求後,通過約定好的通信協議來處理該請求,然後做反序列化,完成後,將請求放入線程池中處理,某個線程接收到這個請求然後找到對應的接口實現進行調用,然後將調用結果原路返回。

Registry

即服務註冊與發現的註冊中心,註冊中心負責服務地址的註冊與查找,相當於服務目錄,服務提供者和消費者隻會再啟動時與註冊中心交互,註冊中心不轉發請求,壓力小。

在這裡插入圖片描述

註冊中心還可以集中化處理配置以及動態地將變更通知訂閱方。

但是為什麼需要註冊中心呢?沒有註冊中心不可以嗎?

在沒有註冊中心,各服務之間的調用關系是這樣的:

在這裡插入圖片描述

當服務越來越多時,服務URL配置管理變得非常困難,硬件負載均衡器的單點壓力也越來越大,而有瞭註冊中心之後,就可以實現服務的統一管理,並且實現軟負載均衡,降低硬件成本,以下為註冊中心示意圖:

在這裡插入圖片描述

Monitor

即統計服務調用次數和調用時間的監控中心,面對眾多服務,精細化的監控和方便的運維是不可或缺的,對後期維護相當重要。

Container

即服務運行的容器。

架構

在這裡插入圖片描述

圖中的各個節點充當的角色已經介紹過瞭,以下是各節點之間調用關系:

Container服務容器負責啟動,加載以及運行

Provider服務提供者Provider服務提供者啟動時,需要將自身暴露出去讓遠程服務器可以發現,同時向Registry註冊中心註冊自己提供的服務

Consumer服務消費者啟動時,向Registry註冊中心訂閱所需要的服務

Registry註冊中心返回服務提供者列表給消費者,同時如果發生變更,註冊中心將基於長連接推送實時數據給消費者

服務消費者需要調用遠程服務時,會從提供者的地址列表中,基於負載均衡算法選出一臺提供者服務器進行調用,如果調用失敗,會基於集群容錯策略進行調用重試

服務消費者與提供者會在內存中統計調用次數和調用時間,然後通過定時任務將數據發送給Monitor監控中心

高可用性

  • 監控中心宕機後不會對服務造成影響,隻是丟失部分統計數據
  • 註冊中心集群後,任意一臺宕機後,將自動切換到其他註冊中心
  • 當所有註冊中心均宕機後,服務提供者和消費者之間仍然能通過本地記錄瞭彼此信息的緩存進行通訊,但是如果一方產生變更,另外一方無法感知
  • 服務提供者無狀態,任意一臺服務器宕機後不影響使用,會有其他服務提供者提供服務
  • 當所有服務提供者宕機後,服務消費者無法正常使用,將進行無限次重連等待服務提供者重新連線恢復

框架設計

在這裡插入圖片描述

大的分層為Business(業務邏輯層)、RPC層和Remoting層。

再細分下來,Dubbo一共有十層架構,作用分別如下:

Service,業務層,即日常開發中的業務邏輯層

Config,配置層,對外配置接口,以ServiceConfigReferenceConfig為中心,可以直接初始化配置類,也可以通過Spring解析配置生成配置類

Proxy,服務代理層,服務接口透明代理,生成服務的客戶端Stub和客戶端Skeleton,負責遠程調用和返回結果

Registry,註冊中心層,封裝服務地址的註冊與發現,以服務URL為中心,拓展接口為RegistryFactoryRegistryRegistryService

Cluster路由和集群容錯層,封裝瞭多個提供者的路由、負載均衡以及集群容錯,並橋接註冊中心,負責通過負載均衡選取調用具體的節點,處理特殊調用請求和負責遠程調用失敗的容錯措施

Monitor,監控層,負責監控統計RPC調用次數和調用時間

Portocol,遠程調用層,主要封裝RPC遠程調用方法

Exchange,信息交換層,用於封裝請求響應模型

Transport,網絡傳輸層,抽象化網絡傳輸統一接口,有MinaNetty可供使用

Serialize,序列化層,將數據序列化成二進制流進行傳輸,也可以反序列化接收數據

服務暴露過程

首先Provider啟動,Protocal通過Proxy代理將需要暴露的接口封裝成Invoker,是一個可執行體,然後通過Exporter包裝並發送到註冊中心完成註冊,至此服務就暴露完成。

在這裡插入圖片描述

服務消費過程

在這裡插入圖片描述

註:上圖中藍色部分為服務消費者,綠色部分為服務提供者。

服務消費者啟動時會向註冊中心訂閱並拉取所需服務提供者的信息,並保存到本地緩存,由此即使所有註冊中心宕機後,服務提供者和服務消費者也可以通過本地緩存進行通訊,隻是一方出現瞭信息變更,另一方無法感知,但並不影響服務的進行。

之後整個服務消費流程從圖中的Proxy開始,由代理類完成處理,以此到達透明無感知。

ProxyFactory生成一個Proxy代理類,Proxy持有一個Invoker可執行對象,調用invoke之後需要通過ClusterDirectory中獲取所有可調用的遠程服務Invoker列表,如果配置瞭某些路由規則,還需要再過濾一遍Invoker列表。

剩下的Invoker再通過LoadBalance做負載均衡選取一個,還需要再通過Filter進行一些數據統計,之後將這些數據保存下來,定時發送給Monitor

接下來用Client做數據傳輸,一般用Netty進行傳輸。

傳輸需要通過Codec接口進行協議構造,然後再通過Serialization進行序列化,最後將序列化後的二進制流發送至給對應的服務提供者。

服務提供者接收到二進制流後也會進行Codec協議處理,然後進行反序列化(此處的處理與傳輸之前的處理是呈對稱的)後將請求放入線程池中處理,某個線程會根據請求找到對應的Exporter,然後再通過Filter進行層層過濾得到Invoker,最終調用對應的實現類然後將結果原路返回。

如有錯誤或不足歡迎評論指正。

以上就是java開發分佈式服務框架Dubbo原理機制詳解的詳細內容,更多關於Dubbo分佈式服務框架原理機制的資料請關註WalkonNet其它相關文章!

推薦閱讀: