微服務面試必問的Dubbo,這麼詳細還怕自己找不到工作?

淺羽技術發表於2021-03-29

大家好,我是小羽。

Dubbo 起源於阿里巴巴,對於我們做電商開發的人來說,基本是首選的技術,那麼為何一個區區 soa 服務治理框架,會受到這麼多人的青睞呢?

今天就跟著小羽一起看看這個微服務框架之一的 Dubbo 的詳細解讀吧。

前言

網際網路的不斷髮展,網站應用的規模不斷擴大,常規的垂直應用架構已無法應對。

服務化的進一步發展,服務越來越多,服務之間的呼叫和依賴關係也越來越複雜,誕生了面向服務的架構體系(SOA),

也因此衍生出了一系列相應的技術,如對服務提供、服務呼叫、連線處理、通訊協議、序列化方式、服務發現、服務路由、日誌輸出等行為進行封裝的服務框架。

就這樣分散式系統的服務治理框架就出現了,Dubbo也就這樣產生了。

概念

Dubbo 是一款高效能、輕量級的開源 RPC 框架、提供服務自動註冊、自動發現等高效治理方案,可以和 Spring 框架無縫整合

簡單的說,dubbo就是個分散式服務框架,在有分散式需要的時候可以使用 dubbo 的框架,使用 dubbo 的好處:

_1、_透明化的遠端方法呼叫

_2、_軟負載均衡及容錯機制

_3、_服務自動註冊與發現

_4、_提供了完善的服務介面管理與監控功能

image
架構圖

RPC

簡介

RPC 全稱為 remote procedure call,即遠端過程呼叫。比如兩臺伺服器 A 和 B,A 伺服器上部署一個應用,B 伺服器上部署一個應用,A 伺服器上的應用想呼叫 B 伺服器上的應用提供的方法,由於兩個應用不在一個記憶體空間,不能直接呼叫,所以需要通過網路來表達呼叫的語義和傳達呼叫的資料

RPC 並不是一個具體的技術,而是指整個網路遠端呼叫過程

RPC 是一個泛化的概念,嚴格來說一切遠端過程呼叫手段都屬於 RP C範疇。各種開發語言都有自己的 RPC 框架。Java 中的 RPC 框架比較多,廣泛使用的有 RMI、Hessian、Dubbo 等。

原理

服務消費方(client)呼叫以本地呼叫方式呼叫服務。客戶端存根(client stub)接收到呼叫後負責將方法、引數等編碼成能在網路中傳輸的訊息體。然後,客戶端存根找到服務地址後,將訊息傳送給服務端。

服務提供方(server)收到序列化後的訊息,就按照解碼該訊息。然後,根據解碼結果呼叫本地服務,執行完畢後,將結果打包傳送給消費方。

服務消費方收到執行結果後,也是進行解碼後得到結果。
image
原理

使用場景

RPC 分散式服務,拆分應用進行服務化,提高開發效率,調優效能,節省競爭資源

_配置管理,_解決服務的地址資訊劇增,配置困難的問題

_服務依賴,_解決服務間依賴關係錯蹤複雜的問題

_服務擴容,_解決隨著訪問量的不斷增大,動態擴充套件服務提供方的機器的問題

核心功能

Remoting:遠端通訊,提供對多種 NIO 框架抽象封裝,包括“同步轉非同步”和“請求-響應”模式的資訊交換方式。

Cluster:服務框架,提供基於介面方法的透明遠端過程呼叫,包括多協議支援,以及軟負載均衡,失敗容錯,地址路由,動態配置等叢集支援。

Registry:服務註冊中心,服務自動發現: 基於註冊中心目錄服務,使服務消費方能動態的查詢服務提供方,使地址透明,使服務提供方可以平滑增加或減少機器。

核心元件

_Provider:_服務的提供方

_Consumer:_呼叫遠端服務的服務消費方

_Registry:_服務註冊和發現的註冊中心

_Monitor:_統計服務呼叫次數和呼叫時間的監控中心

_Container:_服務執行容器
image
元件

服務註冊與發現

流程如下:

_1、_Provider(提供者)繫結指定埠並啟動服務

_2、_供者連線註冊中心,併發本機 IP、埠、應用資訊和提供服務資訊傳送至註冊中心儲存

_3、_Consumer(消費者),連線註冊中心 ,並傳送應用資訊、所求服務資訊至註冊中心

_4、_註冊中心根據消費者所求服務資訊匹配對應的提供者列表傳送至Consumer 應用快取。

_5、_Consumer 在發起遠端呼叫時基於快取的消費者列表擇其一發起呼叫

_6、_Provider 狀態變更會實時通知註冊中心、在由註冊中心實時推送至Consumer設計的原因:

Consumer 與 Provider 解偶,雙方都可以橫向增減節點數。註冊中心對本身可做對等叢集,可動態增減節點,並且任意一臺宕掉後,將自動切換到另一臺

_7、_去中心化,雙方不直接依懶註冊中心,即使註冊中心全部當機短時間內也不會影響服務的呼叫

_8、_服務提供者無狀態,任意一臺宕掉後,不影響使用
image
流程

服務治理

治理原因

Dubbo的服務治理主要原因:

_1、_過多的服務 URL 配置困難

_2、_負載均衡分配節點壓力過大的情況下也需要部署叢集。

_3、_服務依賴混亂,啟動順序不清晰。

_4、_過多服務導致效能指標分析難度較大,需要監控。

主要特性

_透明遠端呼叫:_就像呼叫本地方法一樣呼叫遠端方法;只需簡單配置,沒有任何 API 侵入

_負載均衡機制:_Client 端 LB,可在內網替代 F5 等硬體負載均衡器

_容錯重試機制:_服務 Mock 資料,重試次數、超時機制等

_自動註冊發現:_註冊中心基於介面名查詢服務提 供者的 IP 地址,並且能夠平滑新增或刪除服務提供者

_效能日誌監控:_Monitor 統計服務的呼叫次調和呼叫時間的監控中心

_服務治理中心:_路由規則,動態配置,服務降級,訪問控制,權重調整,負載均衡,等手動配置

_自動治理中心:_無,比如:熔斷限流機制、自動權重調整等(因此可以搭配SpringCloud的熔斷機制等進行開發)
image
服務治理

架構設計

整體架構

先看下 Dubbo 的整體架構圖:

圖例說明:
image
整體架構

圖中左邊淡藍背景的為服務消費方使用的介面,右邊淡綠色背景的為服務提供方使用的介面,位於中軸線上的為雙方都用到的介面。

圖中從下至上分為十層,各層均為單向依賴,右邊的黑色箭頭代表層之間的依賴關係,每一層都可以剝離上層被複用,其中,ServiceConfig 層為 API,其它各層均為 SPI。

圖中綠色小塊的為擴充套件介面,藍色小塊為實現類,圖中只顯示用於關聯各層的實現類。

圖中藍色虛線為初始化過程,即啟動時組裝鏈,紅色實線為方法呼叫過程,即執行時調時鏈,紫色三角箭頭為繼承,可以把子類看作父類的同一個節點,線上的文字為呼叫的方法。

各層說明

_config 配置層:_對外配置介面,以 ServiceConfig, ReferenceConfig 為中心,可以直接初始化配置類,也可以通過 spring 解析配置生成配置類

_proxy 服務代理層:_服務介面透明代理,生成服務的客戶端 Stub 和伺服器端 Skeleton,以ServiceProxy 為中心,擴充套件介面為 ProxyFactory

_registry 註冊中心層:_封裝服務地址的註冊與發現,以服務 URL 為中心,擴充套件介面為RegistryFactory, Registry, RegistryService

_cluster 路由層:_封裝多個提供者的路由及負載均衡,並橋接註冊中心,以 Invoker 為中心,擴充套件介面為 Cluster, Directory, Router, LoadBalance

_monitor 監控層:_RPC 呼叫次數和呼叫時間監控,以 Statistics 為中心,擴充套件介面為MonitorFactory, Monitor, MonitorService

_protocol 遠端呼叫層:_封裝 RPC 呼叫,以 Invocation, Result 為中心,擴充套件介面為 Protocol, Invoker, Exporter

_exchange 資訊交換層:_封裝請求響應模式,同步轉非同步,以 Request, Response 為中心,擴充套件介面為 Exchanger, ExchangeChannel, ExchangeClient, ExchangeServer

_transport 網路傳輸層:_抽象 mina 和 netty 為統一介面,以 Message 為中心,擴充套件介面為 Channel, Transporter, Client, Server, Codec

_serialize 資料序列化層:_可複用的一些工具,擴充套件介面為 Serialization, ObjectInput, ObjectOutput, ThreadPool

主要模組

dubbo-common 公共邏輯模組,包括 Util 類和通用模型

dubbo-remoting 遠端通訊模組,相當於 Dubbo 協議的實現,如果 RPC 用 RMI 協議則不需要使用此包。

dubbo-rpc 遠端呼叫模組,抽象各種協議,以及動態代理,只包含一對一的呼叫,不關心叢集的管理。

dubbo-cluster 叢集模組,將多個服務提供方偽裝為一個提供方,包括:負載均衡、容錯、路由等,叢集的地址列表可以是靜態配置的,也可以是由註冊中心下發。

dubbo-registry 註冊中心模組,基於註冊中心下發地址的叢集方式,以及對各種註冊中心的抽象。

dubbo-monitor 監控模組,統計服務呼叫次數,呼叫時間的,呼叫鏈跟蹤的服務。

dubbo-config 配置模組,是 Dubbo 對外的 API ,使用者通過 Config 使用 Dubbo ,隱藏 Dubbo 所有細節。

dubbo-container 容器模組,是一個 Standalone 的容器,以簡單的 Main 載入 Spring 啟動,因為服務通常不需要 Tomcat/JBoss 等 Web 容器的特性,沒必要用 Web 容器去載入服務。
image
主要模組

呼叫方式

非同步呼叫

基於 NIO 的非阻塞實現並行呼叫,客戶端不需要啟動多執行緒即可完成並行呼叫多個遠端服務,相對多執行緒開銷較小
image
非同步呼叫

本地呼叫

使用了Injvm協議,是一個偽協議,它不開啟埠,不發起遠端呼叫,只在JVM內直接關聯,但執行Dubbo的Filter鏈。

Define injvm protocol:

<dubbo:protocol name="injvm" /> 

Set default protocol:

`<dubbo:provider protocol="injvm" />`

Set service protocol:

<dubbo:service protocol="injvm" />

Use injvm first:(服務暴露與服務引用都需要宣告injvm=“true”)

`<dubbo:consumer injvm="true" .../>`
`<dubbo:provider injvm="true" .../>`
`或`
`<dubbo:reference injvm="true" .../>   <dubbo:service injvm="true" .../>`

容錯機制

呼叫流程

_1、_Cluster 將 Directory 中的多個 Invoker 偽裝成一個Invoker,對上層透明,偽裝過程包含了容錯邏輯

_2、_Router 負責從多個 Invoker 中按路由規則選出子集,比如讀寫分離,應用隔離等

_3、_LoadBalance 負責從多個 Invoker 中選出具體的一個用於本次呼叫,選的過程包含了負載均衡演算法
image
呼叫流程

容錯策略

Dubbo 官網提出總共有六種容錯策略

_1、_Failover Cluster

失敗自動切換,當出現失敗,重試其它伺服器。(預設)

_2、_Failfast Cluster

快速失敗,只發起一次呼叫,失敗立即報錯。通常用於非冪等性的寫操作,比如新增記錄。

_3、_Failsafe Cluster

失敗安全,出現異常時,直接忽略。通常用於寫入審計日誌等操作。

_4、_Failback Cluster

失敗自動恢復,後臺記錄失敗請求,定時重發。通常用於訊息通知操作。

_5、_Forking Cluster

並行呼叫多個伺服器,只要一個成功即返回。通常用於實時性要求較高的讀操作,但需要浪費更多服務資源。
可通過 forks=”2”來設定最大並行數。

_6、_Broadcast Cluster

廣播呼叫所有提供者,逐個呼叫,任意一臺報錯則報錯。(2.1.0 開始支援) 通常用於通知所有提供者更新快取或日誌等本地資源資訊。

總結:在實際應用中查詢語句容錯策略建議使用預設 Failover Cluster,而增刪改建議使用 Failfast Cluster 或者使用 Failover Cluster(retries=”0”)策略,防止出現資料重複新增等等其它問題!建議在設計介面時候把查詢介面方法單獨做一個介面提供查詢。

連線方式

Dubbo 的客戶端和服務端有三種連線方式,分別是:廣播、直連和使用Zookeeper註冊中心。

Dubbo 廣播

這種方式是dubbo官方入門程式所使用的連線方式,但是這種方式有很多問題,在企業開發中不使用廣播的方式。

服務端配置:

`<!--配製dubbo-->`
`<!--提供應用資訊,用於計算依賴關係-->`
`<dubbo:application name="demo-service"/>`
`<!--使用multicast廣播註冊暴露服務地址-->`
`<dubbo:registry address="multicast://192.168.9.4:88888" />`
`<!--使用dubbo協議在20880埠暴露服務-->`
`<dubbo:protocol name="dubbo" port="20880"/>`
`<!--宣告暴露的服務介面-->`
`<dubbo:service interface="com.demo.manger.service.TestService" ref="testServiceImpl" />`

客戶端配置:

`<!--配合dubbo-->`
`<!--提供應用資訊,用於計算依賴關係-->`
`<dubbo:application name="demo-web"/>`
`<!--使用multicast廣播註冊中心暴露服務地址 -->`
`<dubbo:registry address="multicast://19.188.8.9:8888"/>`
`<!--宣告需要暴露的介面-->`
`<dubbo:reference interface="com.demo.manager.service.TestService" id="testService" timeout="1000000" />`

Dubbo 直連

這種方式在企業中一般在開發中環境中使用,但是生產環境很少使用,因為服務是直接呼叫,沒有使用註冊中心,很難對服務進行管理。Dubbo 直連,首先要取消廣播,然後客戶端直接到指定需要的服務的 url 獲取服務即可。

服務端配置:

`<!--配製dubbo-->`
`<!--提供應用資訊,用於計算依賴關係-->`
`<dubbo:application name="demo-service"/>`
`<!--使用multicast廣播註冊暴露服務地址-->`
`<-- <dubbo:registry address="multicast://192.168.9.4:88888" /> -->`
`<dubbo:registry adress="N/A">`
`<!--使用dubbo協議在20880埠暴露服務-->`
`<dubbo:protocol name="dubbo" port="20880"/>`
`<!--宣告暴露的服務介面-->`
`<dubbo:service interface="com.demo.manger.service.TestService" ref="testServiceImpl" />`

客戶端配置:

`<!--配合dubbo-->`
`<!--提供應用資訊,用於計算依賴關係-->`
`<dubbo:application name="demo-web"/>`
`<!--使用multicast廣播註冊中心暴露服務地址 -->`
`<-- <dubbo:registry address="multicast://19.188.8.9:8888"/> -->`
`<!--宣告需要暴露的介面-->`
`<dubbo:reference interface="com.demo.manager.service.TestService" id="testService" timeout="1000000" url="dubbo://127.0.0.1:20880" />`

zookeeper 註冊中心

Dubbo 註冊中心和廣播註冊中心配置類似,不過需要指定註冊中心型別和註冊中心地址,這個時候就不是把服務資訊進行廣播了,而是告訴給註冊中心進行管理,這個時候我們就需要有一個註冊中心,官方推薦使用 zookeeper 作為註冊中心。
image
Zookeeper 註冊中心

註冊中心負責服務地址的註冊與查詢,相當於目錄服務,服務提供者在啟動時與註冊中心互動,消費者不斷的發起請求獲取服務資訊,註冊中心不轉發請求,壓力較小

服務端配置:

`<!--配製dubbo-->`
`<!--提供應用資訊,用於計算依賴關係-->`
`<dubbo:application name="demo-service"/>`
`<!--使用multicast廣播註冊暴露服務地址-->`
`<!-- <dubbo:registry address="multicast://192.168.9.4:88888" /> -->`
`<!--<dubbo:registry adress="N/A"> -->`
`<dubbo:registry protocol="zookeeper" address="192.168.37,136:2181">`
`<!--使用dubbo協議在20880埠暴露服務-->`
`<dubbo:protocol name="dubbo" port="20880"/>`
`<!--宣告暴露的服務介面-->`
`<dubbo:service interface="com.demo.manger.service.TestService" ref="testServiceImpl" />`

客戶端配置:

`<!--配合dubbo-->`
`<!--提供應用資訊,用於計算依賴關係-->`
`<dubbo:application name="demo-web"/>`
`<!--使用multicast廣播註冊中心暴露服務地址 -->`
`<-- <dubbo:registry address="multicast://19.188.8.9:8888"/> -->`
`<dubbo:registry protocol="zookeeper" address="192.168.37.1336:2181"/>` 
`<!--宣告需要暴露的介面-->`
`<dubbo:reference interface="com.demo.manager.service.TestService" id="testService" timeout="1000000" />`

策略

負載均衡策略

_1、_Random LoadBalance,隨機(預設的負載均衡策略)

RandomLoadBalance 是加權隨機演算法的具體實現,可以完全隨機,也可以按權重設定隨機概率。

_2、_RoundRobin LoadBalance,輪循

可以輪詢和加權輪詢。存在響應慢的提供者會累積請求的問題,比如:第二臺機器很慢,但沒掛,當請求調到第二臺時就卡在那,久而久之,所有請求都卡在調到第二臺上。

_3、_LeastActive LoadBalance,最少活躍呼叫數

活躍呼叫數越小,表明該服務提供者效率越高,單位時間內可處理更多的請求。此時應優先將請求分配給該服務提供者。

_4、_ConsistentHash LoadBalance,一致性 Hash

一致性 Hash 演算法,相同引數的請求一定分發到一個 provider 上去。provider 掛掉的時候,會基於虛擬節點均勻分配剩餘的流量,抖動不會太大。

叢集容錯策略

_1、_failover cluster(預設)

失敗自動切換,呼叫失敗時,自動重試其他機器。通常用於讀操作,但重試會帶來更長延遲。

_2、_Failfast Cluster
快速失敗,只發起一次呼叫,失敗立即報錯。通常用於非冪等性的寫操作,比如新增記錄。

_3、_Failsafe Cluster
失敗安全,出現異常時,直接忽略。通常用於寫入審計日誌等操作。

_4、_Failback Cluster
失敗自動恢復,後臺記錄失敗請求,定時重發。通常用於訊息通知操作。

_5、_Forking Cluster
並行呼叫多個伺服器,只要一個成功即返回。通常用於實時性要求較高的讀操作,但需要浪費更多服務資源。

動態代理策略

預設使用 javassist 動態位元組碼生成,建立代理類。也可以通過 spi 擴充套件機制配置自己的動態代理策略。

叢集容錯方案

  • 配置說明,方案配置方式,優先使用消費端配置
`<!--服務端配置-->`
`<dubbo:service cluster="failover"/>`
`<!--消費端配置-->`
`<dubbo:reference cluster="failover"/>`

  • 儘量在只在服務端進行配置

  • cluster型別均為小寫

  • 預設為FailoverCluster失敗切換方案

叢集容錯方案support

FailoverCluster(預設):失敗切換

  • 場景:呼叫失敗後切換其他服務

  • 配置:

`<!--`
`retries:重試次數,不包括第一次,預設2次`
`-->`
`<dubbo:service cluster="failover" retries="3"/>`

  • 程式碼實現邏輯:

    1. 根據負載均衡策略選出需要呼叫的服務例項,排除已呼叫的

    2. 執行選出的例項,並將其儲存到已呼叫列表中

    3. 執行例項成功即返回

    4. 執行例項不成功,為到最大重試次數則執行第一步,否則丟擲RpcException異常

FailbackCluster:失敗重試

  • 場景:呼叫失敗時記錄失敗請求,定時重發

  • 配置:

`<!--`
`retries:重試次數,不包括第一次,預設3次`
`failbacktasks:定時器中最大掛起任務數,預設100`
`-->`
`<dubbo:service cluster="failback" retries="5" failbacktasks="200"/>`

  • 程式碼實現邏輯

    1. 根據負載均衡策略選出需要呼叫的服務例項

    2. 執行選出的例項

    3. 執行例項成功即返回

    4. 執行異常則建立延時5秒的定時任務,並加入時間輪定時器,第一次需要進行定時器初始化,分為32個時間片,每1秒滾動一次,最大掛起任務預設100個,超出最大任務數時丟擲RejectedExecutionException異常。

    5. 重試執行定時任務,次數超出最大執行次數停止,並輸出error日誌,預設為3次。

FailfastCluster:快速失敗

  • 場景:呼叫失敗立即報錯

  • 配置:

`<dubbo:service cluster="failfast"/>`

  • 程式碼實現邏輯

    1. 根據負載均衡策略選出需要呼叫的服務例項

    2. 執行選出的例項

    3. 執行例項成功即返回,失敗丟擲RpcException異常

FailsafeCluster:安全失敗

  • 場景:呼叫失敗後忽略

  • 配置:

`<dubbo:service cluster="failsafe"/>`

  • 程式碼實現邏輯

    1. 根據負載均衡策略選出需要呼叫的服務例項

    2. 執行選出的例項

    3. 執行例項成功即返回,失敗輸出error日誌,並返RpcResult,視為忽略。

ForkingCluster:併發處理

  • 場景:併發呼叫指定數量的服務,一個成功則返回,對實時性要求高的場景,要求快速返回,需要使用更多伺服器資源。

  • 配置:

`<!--`
`forks:最大併發數,預設2`
`timeout:併發返回超時時間,預設1000ms`
`-->`
`<dubbo:service cluster="forking" forks="3" timeout="500"/>`

  • 程式碼實現邏輯

    1. 根據負載均衡策略選出幾個不同的服務例項

    2. 併發執行選出的幾個例項,並將返回結果放入堵塞佇列中

    3. 返回堵塞佇列中的第一個值,如規定時間內未獲取到佇列中的值或獲取到異常值則返回RPC異常。

BroadcastCluster:廣播

  • 場景:廣播方式逐個呼叫服務提供者,有一個報錯則返回錯誤,多用於通知服務提供者更新本地資源資訊,如快取,日誌等。

  • 配置:

`<dubbo:service cluster="broadcast"/>`

  • 程式碼實現邏輯

    1. 迴圈逐個執行所有服務例項資訊

    2. 儲存一份返回結果和異常資訊

    3. 執行完全部例項後,如異常資訊不為空,則丟擲異常資訊,否則返回最後一個例項的結果。

AvailableCluster:可用服務

  • 場景:呼叫第一個可用服務

  • 配置:

`<dubbo:service cluster="available"/>`

  • 程式碼實現邏輯

    1. 迴圈所有服務例項資訊

    2. 執行第一個可用的例項,並返回結果

    3. 如無可用例項則返回RpcException異常

MergeableCluster:合併處理

  • 場景:返回合併或疊加處理結果

  • 配置:

`<!--`
`merger:合併發放名`
`timeout:呼叫服務超時時間,預設1000ms`
`-->`
`<dubbo:service cluster="mergeable" merger="true" timeout="500"/>`

  • 程式碼實現邏輯

    1. 判斷merger,為空、null、0、false、N/A是執行第一個可用服務並返回結果,無可用則執行第一個例項,並返回結果。

    2. 獲取方法例項的返回型別

    3. 非同步呼叫所有例項,並將非同步結果Result儲存到結果集中,返回異常輸出error日誌

    4. 結果集為空返回 RpcException,大小為 1時返回第一個Result

    5. 當merger的第一個字元為“.”時,判斷當 merger 例項返回型別不為void,且返回型別必須是結果集中第一個返回型別的父型別或相同型別時,迴圈執行merger例項,每一次都傳入上一次的返回結果,最終返回獲取最後一次結果,非上述情況時迴圈執行merger例項,返回結果集中的第一個結果。

    6. 當merger為true或default時使用Dubbo預設合併器,否則使用自定義merger合併器,合併後返回

RegistryAwareCluster:預設標識、註冊標識

  • 場景:呼叫註冊預設標識的服務

  • 配置:

`<!--`
`default:預設標識`
`-->`
`<dubbo:registry address="zookeeper://xxx..." default="true"/>`
`<dubbo:service cluster="registryaware"/>`

  • 程式碼實現邏輯

    1.8 迴圈所有服務例項資訊

    2. 執行第一個可用的例項且default為true的例項

    3. 無預設例項則執行第一個可用的例項

    4. 無可用的例項則丟擲RpcException異常

主要配置

配置應用資訊:

`<dubbo:application name=“appName-provider” />`

配置註冊中心相關資訊:

`<dubbo:registryid=“zk” protocol=“zookeeper” address=“127.0.0.1:2181” />`

配置服務協議:

`<dubbo:protocol name=“dubbo” port=“20880” threadpool=“cached” threads=“80” />`

配置所有暴露服務預設值:

`<dubbo:provider registry=“zk” protocol=“dubbo” retries=“0” version=“1.0.0” timeout=“3000” threadpool=“cached” threads=“4”/>`

配置暴露服務:

`<dubbo:service interface=“com.orgname.app.serviceX” ref=“serviceX” />`

配置所有引用服務預設值:

`<dubbo:consumer check=“false” timeout=“1000” version=“1.0” retries=“0” async=“false” />`

註解配置:

`com.alibaba.dubbo.config.annotation.Service 配置暴露服務`
`com.alibaba.dubbo.config.annotation.Reference配置引用服務`

超時設定

Dubbo消費端

全域性超時配置

`<dubbo:consumer timeout="5000" />`

指定介面以及特定方法超時配置

`<dubbo:reference interface="com.foo.BarService" timeout="2000">`
 `<dubbo:method name="sayHello" timeout="3000" />`
`</dubbo:reference>`

Dubbo服務端

全域性超時配置

`<dubbo:provider timeout="5000" />`

指定介面以及特定方法超時配置

`<dubbo:provider interface="com.foo.BarService" timeout="2000">`
 `<dubbo:method name="sayHello" timeout="3000" />`
`</dubbo:provider>`

支援協議

_1、_Dubbo 協議(官方推薦協議)

優點:採用NIO複用單一長連線,並使用執行緒池併發處理請求,減少握手和加大併發效率,效能較好(推薦使用)

缺點:大檔案上傳時,可能出現問題(不使用 Dubbo 檔案上傳)

_2、_RMI(Remote Method Invocation)協議

優點:JDK 自帶的能力。可與原生 RMI 互操作,基於 TCP 協議

缺點:偶爾連線失敗.

_3、_Hessian協議

優點:可與原生 Hessian 互操作,基於 HTTP 協議

缺點:需 hessian.jar 支援,http 短連線的*_開銷大_8

常用設計模式

Dubbo 框架在初始化和通訊過程中使用了多種設計模式,可靈活控制類載入、許可權控制等功能。

工廠模式

Provider 在 export 服務時,會呼叫 ServiceConfig 的 export 方法。ServiceConfig 中有個欄位:

`private static final Protocol protocol =`
`ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();`

Dubbo 裡有很多這種程式碼。這也是一種工廠模式,只是實現類的獲取採用了 JDK SPI 的機制。這麼實現的優點是可擴充套件性強,想要擴充套件實現,只需要在 classpath下增加個檔案就可以了,程式碼零侵入。另外,像上面的 Adaptive 實現,可以做到呼叫時動態決定呼叫哪個實現,但是由於這種實現採用了動態代理,會造成程式碼除錯比較麻煩,需要分析出實際呼叫的實現類。

裝飾器模式

Dubbo 在啟動和呼叫階段都大量使用了裝飾器模式。以 Provider 提供的呼叫鏈為例,具體的呼叫鏈程式碼是在 ProtocolFilterWrapper 的buildInvokerChain 完成的,具體是將註解中含有 group=provider 的 Filter 實現,按照 order 排序,最後的呼叫順序是:

`EchoFilter -> ClassLoaderFilter -> GenericFilter -> ContextFilter ->`
`ExecuteLimitFilter -> TraceFilter -> TimeoutFilter -> MonitorFilter ->`
`ExceptionFilter`

更確切地說,這裡是裝飾器和責任鏈模式的混合使用。例如,EchoFilter 的作用是判斷是否是回聲測試請求,是的話直接返回內容,這是一種責任鏈的體現。而像ClassLoaderFilter 則只是在主功能上新增了功能,更改當前執行緒的 ClassLoader,這是典型的裝飾器模式。

觀察者模式

Dubbo 的 Provider 啟動時,需要與註冊中心互動,先註冊自己的服務,再訂閱自己的服務,訂閱時,採用了觀察者模式,開啟一個 listener。註冊中心會每 5 秒定時檢查是否有服務更新,如果有更新,向該服務的提供者傳送一個 notify 訊息,provider 接受到 notify 訊息後,即執行 NotifyListener 的 notify 方法,執行監聽器方法。

動態代理模式

Dubbo 擴充套件 JDK SPI 的類 ExtensionLoader 的 Adaptive 實現是典型的動態代理實現。Dubbo 需要靈活地控制實現類,即在呼叫階段動態地根據引數決定呼叫哪個實現類,所以採用先生成代理類的方法,能夠做到靈活的呼叫。生成代理類的程式碼是 ExtensionLoader 的 createAdaptiveExtensionClassCode 方法。代理類的主要邏輯是,獲取 URL 引數中指定引數的值作為獲取實現類的 key

工作流程

整體流程:

第一步:provider 向註冊中心去註冊

第二步:consumer 從註冊中心訂閱服務,註冊中心會通知 consumer 註冊好的服務

第三步:consumer 呼叫 provider

第四步:consumer 和 provider 都非同步通知監控中心
image
流程圖

總結

最後用一張圖來形象的模擬 Dubbo 的使用:
image
使用

以上只是我總結的一些關於 dubbo 最基礎的原理及使用介紹,至於程式碼編寫過程的 bug 處理經驗,環境搭建、專案佈局等等問題,需要我們在平時開發中,將系統知識與實戰經驗相結合去總結,這樣才能真正的去掌握這項技術點。

Dubbo 目前是我用到過的最多的分散式框架,寫出來的內容也是最多的,不過由於Dubbo用的太多,而 SpringCloud 難度比 Dubbo 要小很多,現在大部分專案都即將開始轉投到了 SpringCloud 上面,後面也會出更多的 SpringCloud 相關的文章。

相關文章