1. 程式人生 > >dubbo學習(一)dubbo簡介與原理

dubbo學習(一)dubbo簡介與原理

一、Dubbo背景和簡介

  1. 單一應用框架(ORM) 
    當網站流量很小時,只需一個應用,將所有功能如下單支付等都部署在一起,以減少部署節點和成本。 
    缺點:單一的系統架構,使得在開發過程中,佔用的資源越來越多,而且隨著流量的增加越來越難以維護 
    這裡寫圖片描述

  2. 垂直應用框架(MVC) 
    垂直應用架構解決了單一應用架構所面臨的擴容問題,流量能夠分散到各個子系統當中,且系統的體積可控,一定程度上降低了開發人員之間協同以及維護的成本,提升了開發效率。 
    缺點:但是在垂直架構中相同邏輯程式碼需要不斷的複製,不能複用。 
    這裡寫圖片描述

  3. 分散式應用架構(RPC) 
    當垂直應用越來越多,應用之間互動不可避免,將核心業務抽取出來,作為獨立的服務,逐漸形成穩定的服務中心 
    這裡寫圖片描述

  4. 流動計算架構(SOA) 
    隨著服務化的進一步發展,服務越來越多,服務之間的呼叫和依賴關係也越來越複雜,誕生了面向服務的架構體系(SOA),也因此衍生出了一系列相應的技術,如對服務提供、服務呼叫、連線處理、通訊協議、序列化方式、服務發現、服務路由、日誌輸出等行為進行封裝的服務框架

從以上是電商系統的演變可以看出架構演變的過程: 
這裡寫圖片描述

  • 單一應用架構

    • 當網站流量很小時,只需一個應用,將所有功能都部署在一起,以減少部署節點和成本。
    • 此時,用於簡化增刪改查工作量的 資料訪問框架(ORM) 是關鍵。
  • 垂直應用架構

    • 當訪問量逐漸增大,單一應用增加機器帶來的加速度越來越小,將應用拆成互不相干的幾個應用,以提升效率。
    • 此時,用於加速前端頁面開發的 Web框架(MVC) 是關鍵。
  • 分散式服務架構 
    • 當垂直應用越來越多,應用之間互動不可避免,將核心業務抽取出來,作為獨立的服務,逐漸形成穩定的服務中心,使前端應用能更快速的響應多變的市場需求。
    • 此時,用於提高業務複用及整合的 分散式服務框架(RPC) 是關鍵。
  • 流動計算架構 
    • 當服務越來越多,容量的評估,小服務資源的浪費等問題逐漸顯現,此時需增加一個排程中心基於訪問壓力實時管理叢集容量,提高叢集利用率。
    • 此時,用於提高機器利用率的 資源排程和治理中心(SOA) 是關鍵。

在這裡插播一條關於RPC的簡介: 
RPC(Remote Procedure Call Protocol):遠端過程呼叫

: 
兩臺伺服器A、B,分別部署不同的應用a,b。當A伺服器想要呼叫B伺服器上應用b提供的函式或方法的時候,由於不在一個記憶體空間,不能直接呼叫,需要通過網路來表達呼叫的語義傳達呼叫的資料。 
說白了,就是你在你的機器上寫了一個程式,我這邊是無法直接呼叫的,這個時候就出現了一個遠端服務呼叫的概念。

RPC是一種通過網路從遠端計算機程式上請求服務,而不需要了解底層網路技術的協議。RPC協議假定某些傳輸協議的存在,如TCP或UDP,為通訊程式之間攜帶資訊資料。在OSI網路通訊模型中,RPC跨越了傳輸層和應用層。RPC使得開發包括網路分散式多程式在內的應用程式更加容易。 
RPC採用客戶機/伺服器模式。請求程式就是一個客戶機,而服務提供程式就是一個伺服器。首先,客戶機呼叫程序傳送一個有程序引數的呼叫資訊到服務程序,然後等待應答資訊。在伺服器端,程序保持睡眠狀態直到呼叫資訊到達為止。當一個呼叫資訊到達,伺服器獲得程序引數,計算結果,傳送答覆資訊,然後等待下一個呼叫資訊,最後,客戶端呼叫程序接收答覆資訊,獲得程序結果,然後呼叫執行繼續進行。

RPC需要解決的問題: 
(可以稍作了解,詳情可檢視別的博文)

  • 通訊問題 : 主要是通過在客戶端和伺服器之間建立TCP連線,遠端過程呼叫的所有交換的資料都在這個連線裡傳輸。連線可以是按需連線,呼叫結束後就斷掉,也可以是長連線,多個遠端過程呼叫共享同一個連線。
  • 定址問題 : A伺服器上的應用怎麼告訴底層的RPC框架,如何連線到B伺服器(如主機或IP地址)以及特定的埠,方法的名稱名稱是什麼,這樣才能完成呼叫。比如基於Web服務協議棧的RPC,就要提供一個endpoint URI,或者是從UDDI服務上查詢。如果是RMI呼叫的話,還需要一個RMI Registry來註冊服務的地址。
  • 序列化 與 反序列化 : 當A伺服器上的應用發起遠端過程呼叫時,方法的引數需要通過底層的網路協議如TCP傳遞到B伺服器,由於網路協議是基於二進位制的,記憶體中的引數的值要序列化成二進位制的形式,也就是序列化(Serialize)或編組(marshal),通過定址和傳輸將序列化的二進位制傳送給B伺服器。 
    同理,B伺服器接收引數要將引數反序列化。B伺服器應用呼叫自己的方法處理後返回的結果也要序列化給A伺服器,A伺服器接收也要經過反序列化的過程。

Dubbo是什麼

Dubbo是:

  • 一款分散式服務框架
  • 高效能和透明化的RPC遠端服務呼叫方案
  • SOA服務治理方案

每天為2千多個服務提供大於30億次訪問量支援,並被廣泛應用於阿里巴巴集團的各成員站點以及別的公司的業務中。

二、Dubbo架構

這裡寫圖片描述

Provider: 暴露服務的服務提供方。 
Consumer: 呼叫遠端服務的服務消費方。 
Registry: 服務註冊與發現的註冊中心。 
Monitor: 統計服務的呼叫次數和呼叫時間的監控中心。

呼叫流程 
0.服務容器負責啟動,載入,執行服務提供者。 
1.服務提供者在啟動時,向註冊中心註冊自己提供的服務。 
2.服務消費者在啟動時,向註冊中心訂閱自己所需的服務。 
3.註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連線推送變更資料給消費者。 
4.服務消費者,從提供者地址列表中,基於軟負載均衡演算法,選一臺提供者進行呼叫,如果呼叫失敗,再選另一臺呼叫。 
5.服務消費者和提供者,在記憶體中累計呼叫次數和呼叫時間,定時每分鐘傳送一次統計資料到監控中心

Dubbo註冊中心

對於服務提供方,它需要釋出服務,而且由於應用系統的複雜性,服務的數量、型別也不斷膨脹; 
對於服務消費方,它最關心如何獲取到它所需要的服務,而面對複雜的應用系統,需要管理大量的服務呼叫。 
而且,對於服務提供方和服務消費方來說,他們還有可能兼具這兩種角色,即既需要提供服務,有需要消費服務。

通過將服務統一管理起來,可以有效地優化內部應用對服務釋出/使用的流程和管理。服務註冊中心可以通過特定協議來完成服務對外的統一。

Dubbo提供的註冊中心有如下幾種型別可供選擇

  • Multicast註冊中心
  • Zookeeper註冊中心
  • Redis註冊中心
  • Simple註冊中心

Dubbo優缺點

優點:

  1. 透明化的遠端方法呼叫 
    - 像呼叫本地方法一樣呼叫遠端方法;只需簡單配置,沒有任何API侵入。
  2. 軟負載均衡及容錯機制 
    • 可在內網替代nginx lvs等硬體負載均衡器。
  3. 服務註冊中心自動註冊 & 配置管理 
    -不需要寫死服務提供者地址,註冊中心基於介面名自動查詢提供者ip。 
    使用類似zookeeper等分散式協調服務作為服務註冊中心,可以將絕大部分專案配置移入zookeeper叢集。
  4. 服務介面監控與治理 
    -Dubbo-admin與Dubbo-monitor提供了完善的服務介面管理與監控功能,針對不同應用的不同介面,可以進行 多版本,多協議,多註冊中心管理。

缺點:

  • 只支援JAVA語言

三、dubbo原理

本篇部落格的內容總體上比較抽象,如果一個想馬上使用dubbo的同學來說,讀這篇部落格效果不太好,本篇部落格沒有寫怎麼使用、配置dubbo,接下來,我再令寫一篇dubbo入門包含demo的部落格。

I、初始化過程細節: 
上圖中的第一步start,就是將服務裝載容器中,然後準備註冊服務。和Spring中啟動過程類似,spring啟動時,將bean裝載進容器中的時候,首先要解析bean。所以dubbo也是先讀配置檔案解析服務。 
解析服務: 
1)、基於dubbo.jar內的Meta-inf/spring.handlers配置,spring在遇到dubbo名稱空間時,會回撥DubboNamespaceHandler類。 
2)、所有的dubbo標籤,都統一用DubboBeanDefinitionParser進行解析,基於一對一屬性對映,將XML標籤解析為Bean物件。 
原始碼截圖: 
在ServiceConfig.export 或者ReferenceConfig.get 初始化時,將Bean物件轉會為url格式,將所以Bean屬性轉成url的引數。 
然後將URL傳給Protocol擴充套件點,基於擴充套件點的Adaptive機制,根據URL的協議頭,進行不同協議的服務暴露和引用。 
暴露服務:

a、 只暴露服務埠

在沒有使用註冊中心的情況,這種情況一般適用在開發環境下,服務的呼叫這和提供在同一個IP上,只需要開啟服務的埠即可。 
即,當配置 or 
ServiceConfig解析出的URL的格式為: 
Dubbo://service-host/com.xxx.TxxService?version=1.0.0 
基於擴充套件點的Adaptiver機制,通過URL的“dubbo://”協議頭識別,直接呼叫DubboProtocol的export()方法,開啟服務埠。

b、向註冊中心暴露服務:

和上一種的區別:需要將服務的IP和埠一同暴露給註冊中心。 
ServiceConfig解析出的url格式為: 
registry://registry-host/com.alibaba.dubbo.registry.RegistryService?export=URL.encode(“dubbo://service-host/com.xxx.TxxService?version=1.0.0”)

基於擴充套件點的Adaptive機制,通過URL的“registry://”協議頭識別,呼叫RegistryProtocol的export方法,將export引數中的提供者URL先註冊到註冊中心,再重新傳給Protocol擴充套件點進行暴露: 
Dubbo://service-host/com.xxx.TxxService?version=1.0.0

引用服務:

a、直接引用服務:

在沒有註冊中心的,直連提供者情況下, 
ReferenceConfig解析出的URL格式為: 
Dubbo://service-host/com.xxx.TxxService?version=1.0.0

基於擴充套件點的Adaptive機制,通過url的“dubbo://”協議頭識別,直接呼叫DubboProtocol的refer方法,返回提供者引用。

b、從註冊中心發現引用服務:

此時,ReferenceConfig解析出的URL的格式為: 
registry://registry-host/com.alibaba.dubbo.registry.RegistryService?refer=URL.encode(“consumer://consumer-host/com.foo.FooService?version=1.0.0”)

基於擴充套件點的Apaptive機制,通過URL的“registry://”協議頭識別,就會呼叫RegistryProtocol的refer方法,基於refer引數總的條件,查詢提供者URL,如: 
Dubbo://service-host/com.xxx.TxxService?version=1.0.0

基於擴充套件點的Adaptive機制,通過提供者URL的“dubbo://”協議頭識別,就會呼叫DubboProtocol的refer()方法,得到提供者引用。 
然後RegistryProtocol將多個提供者引用,通過Cluster擴充套件點,偽裝成單個提供這引用返回。

三、遠端呼叫細節:

服務提供者暴露一個服務的詳細過程:

這裡寫圖片描述

上圖是服務提供者暴露服務的主過程: 
首先ServiceConfig類拿到對外提供服務的實際類ref,然後將ProxyFactory類的getInvoker方法使用ref生成一個AbstractProxyInvoker例項,到這一步就完成具體服務到invoker的轉化。接下來就是Invoker轉換到Exporter的過程。 
Dubbo處理服務暴露的關鍵就在Invoker轉換到Exporter的過程,下面我們以Dubbo和rmi這兩種典型協議的實現來進行說明: 
Dubbo的實現: 
Dubbo協議的Invoker轉為Exporter發生在DubboProtocol類的export方法,它主要是開啟socket偵聽服務,並接收客戶端發來的各種請求,通訊細節由dubbo自己實現。 
Rmi的實現: 
RMI協議的Invoker轉為Exporter發生在RmiProtocol類的export方法,他通過Spring或Dubbo或JDK來實現服務,通訊細節由JDK底層來實現。

服務消費者消費一個服務的詳細過程

這裡寫圖片描述

上圖是服務消費的主過程: 
首先ReferenceConfig類的init方法呼叫Protocol的refer方法生成Invoker例項。接下來把Invoker轉為客戶端需要的介面