Dubbo整體概念整理

整理自官網,對整體理解Dubbo很有作用.

作用

Apache Dubbo 是一款高性能,輕量級的Java RPC框架.

三大核心能力

面向接口的遠程方法調用

智能容錯和負載均衡

以及服務自動註冊和發現

健壯性

監控中心宕掉不影響使用,只是丟失部分採樣數據.

數據庫宕掉後,註冊中心仍能通過緩存提供服務列表查詢,但不能註冊新服務.

註冊中心對等集羣,任意一臺宕掉後,將自動切換到另一臺.

註冊中心全部宕掉後,服務提供者 和 服務消費者 仍能通過本地緩存通訊.

服務提供者無狀態,任意一臺宕掉後,不影響使用.

服務提供者全部宕掉後,服務消費者應用將無法使用,並無限次重連等待服務提供者恢復.

伸縮性

註冊中心爲對等集羣,可動態增加機器部署實例,所有客戶端將自動發現新的註冊中心.

服務提供者無狀態,可動態增加機器部署實例,註冊中心將推送新的服務提供者信息給消費者.

協議

  • Dubbo協議
    採用NIO複用單一長連接,並使用線程池併發處理請求,減少握手和加大併發效率,性能較好(推薦使用)
    在大文件傳輸時,單一連接會成爲瓶頸
    可用於生產環境

  • Rmi協議
    可與原生RMI互操作,基於TCP協議
    偶爾會連接失敗,需重建Stub 可用於生產環境

  • Hessian協議
    可與原生Hessian互操作,基於HTTP協議
    需hessian.jar支持,http短連接的開銷大 可用於生產環境

nio框架

  • Netty Transporter
    JBoss 的 NIO 框架,性能較好(推薦使用)
    一次請求派發兩種事件,需屏蔽無用事件.

  • Mina Transporter
    老牌NIO框架,穩定
    待發送消息隊列派發不及時,大壓力下,會出現FullGC.

序列化

  • Hessian Serialization
    Stable 性能較好,多語言支持(推薦使用)
    Hessian的各版本兼容性不好,可能和應用使用的Hessian衝突,Dubbo內嵌了hessian3.2.1的源碼
    可用於生產環境

  • Dubbo Serialization
    Tested
    通過不傳送POJO的類元信息,在大量POJO傳輸時,性能較好
    當參數對象增加字段時,需外部文件聲明 試用

  • Json Serialization
    純文本,可跨語言解析,缺省採用FastJson解析
    性能較差 試用

  • Java Serialization
    Java原生支持 性能較差
    可用於生產環境

生成代理類

  • Javassist ProxyFactory
    通過字節碼生成代替反射,性能比較好(推薦使用)
    依賴於javassist.jar包,佔用JVM的Perm內存,Perm可能要設大一些:java -XX:PermSize=128m
    可用於生產環境

  • Jdk ProxyFactory
    JDK原生支持 性能較差 可用於生產環境

容錯機制

  • Failover Cluster
    失敗自動切換,當出現失敗,重試其它服務器,通常用於讀操作(推薦使用)
    重試會帶來更長延遲

  • Failfast Cluster
    快速失敗,只發起一次調用,失敗立即報錯,通常用於非冪等性的寫操作 如果有機器正在重啓,可能會出現調用失敗 可用於生產環境

  • Failsafe Cluster
    失敗安全,出現異常時,直接忽略,通常用於寫入審計日誌等操作
    調用信息丟失
    可用於生產環境 Monitor

  • Failback Cluster
    失敗自動恢復,後臺記錄失敗請求,定時重發,通常用於消息通知操作
    不可靠,重啓丟失
    可用於生產環境 Registry

  • Forking Cluster
    並行調用多個服務器,只要一個成功即返回,通常用於實時性要求較高的讀操作
    需要浪費更多服務資源
    可用於生產環境

  • Broadcast Cluster
    廣播調用所有提供者,逐個調用,任意一臺報錯則報錯,通常用於更新提供方本地狀態
    速度慢,任意一臺報錯則報錯
    可用於生產環境

負載均衡算法

  • Random LoadBalance
    隨機,按權重設置隨機概率(推薦使用)
    在一個截面上碰撞的概率高,重試時,可能出現瞬間壓力不均

  • RoundRobin LoadBalance
    輪詢,按公約後的權重設置輪詢比率
    存在慢的機器累積請求問題,極端情況可能產生雪崩

  • LeastActive LoadBalance
    最少活躍調用數,相同活躍數的隨機,活躍數指調用前後計數差,使慢的機器收到更少請求
    不支持權重,在容量規劃時,不能通過權重把壓力導向一臺機器壓測容量

  • ConsistentHash LoadBalance
    一致性Hash,相同參數的請求總是發到同一提供者,當某一臺提供者掛時,原本發往該提供者的請求,基於虛擬節點,平攤到其它提供者,不會引起劇烈變動
    壓力分攤不均

線程模型

線程模型

IO線程自行處理:
如果事件處理的邏輯能迅速完成,並且不會發起新的 IO 請求,比如只是在內存中記個標識,則直接在 IO 線程上處理更快,因爲減少了線程池調度.

派發到線程池處理:
但如果事件處理邏輯較慢,或者需要發起新的 IO 請求,比如需要查詢數據庫,則必須派發到線程池,否則 IO 線程阻塞,將導致不能接收其它請求.

如果用 IO 線程處理事件,又在事件處理過程中發起新的 IO 請求,比如在連接事件中發起登錄請求,會報"可能引發死鎖"異常,但不會真死鎖.

分層

業務層: Service

RPC層: Config, Proxy, Registry, Cluster, Monitor, Protocol

Remote層: Exchange, Transport, Serialize

  • Service:
    業務層.包括業務代碼的接口與實現.

  • config 配置層:
    對外配置接口,以 ServiceConfig(暴露的服務配置), ReferenceConfig(引用的服務配置) 爲中心,可以直接初始化配置類,也可以通過 spring 解析配置生成配置類.該層管理整個dubbo的配置.

  • proxy 服務代理層:
    服務代理層.在Dubbo中,無論 服務提供者 還是 服務消費者,框架都會生成一個代理類,整個過程對上層透明.
    當調用一個遠程接口時,看起來就像調用一個本地接口一樣.
    代理層會自動做遠程調用並返回結果,即讓業務層對遠程調用完全無感知.
    服務接口透明代理,生成服務的客戶端 Stub 和服務器端 Skeleton, 以 ServiceProxy 爲中心,擴展接口爲 ProxyFactory

  • registry 註冊中心層:
    負責 Dubbo 框架的服務註冊與發現.當有新的服務加入或舊服務下線時,註冊中心都會感知並通知給所有訂閱方.以服務 URL 爲中心,擴展接口爲 RegistryFactory, Registry, RegistryService

  • cluster 路由層:
    封裝多個提供者的路由及負載均衡,並橋接註冊中心,以 Invoker 爲中心,擴展接口爲 Cluster, Directory, Router, LoadBalance.
    該層主要負責:
    遠程調用失敗時的容錯策略(如失敗重試,快速失敗);
    選擇具體調用節點時的負載均衡策略(如隨機,一致性Hash等);
    特殊調用路徑的路由策略(如某個消費者只會調用某個IP的生產者)

  • monitor 監控層:
    RPC 調用次數和調用時間監控,以 Statistics 爲中心,擴展接口爲 MonitorFactory, Monitor, MonitorService

  • protocol 遠程調用層:
    封裝 RPC 調用具體過程.,以 Invocation, Result 爲中心,擴展接口爲 Protocol, Invoker, Exporter.
    是服務域,它是 Invoker 暴露和引用的主功能入口,它負責 Invoker 的生命週期管理.
    Protocol 是核心層,也就是隻要有 Protocol + Invoker + Exporter 就可以完成非透明的 RPC 調用,然後在 Invoker 的主過程上 Filter 攔截點.
    Invoker 是 Dubbo 的核心模型,框架中所有其他模型都向它靠攏,或者轉換成它,它代表一個 可執行體.
    允許向它發起 invoke 調用,它可能是執行一個本地的接口實現,也可能是一個遠程的實現,還可能是一個集羣實現.

  • exchange 信息交換層:
    建立 Request-Response 模型,封裝請求響應模式,同步轉異步,以 Request, Response 爲中心,擴展接口爲 Exchanger, ExchangeChannel, ExchangeClient, ExchangeServer

  • transport 網絡傳輸層:
    抽象 mina 和 netty 爲統一接口,以 Message 爲中心,擴展接口爲 Channel, Transporter, Client, Server, Codec

  • serialize 數據序列化層:
    若數據要通過網絡進行發送,則需要先做序列化,變成二進制流.
    序列化層負責管理整個框架網絡傳輸時的 序列化/反序列化 工作.
    可複用的一些工具,擴展接口爲 Serialization, ObjectInput, ObjectOutput, ThreadPool

分層關係說明

在 RPC 中,Protocol 是核心層,也就是隻要有 Protocol + Invoker + Exporter 就可以完成非透明的 RPC 調用,然後在 Invoker 的主過程上 Filter 攔截點.

Consumer 和 Provider 是抽象概念,只是想讓看圖者更直觀的瞭解哪些類分屬於客戶端與服務器端,不用 Client 和 Server 的原因是 Dubbo 在很多場景下都使用 Provider, Consumer, Registry, Monitor 劃分邏輯拓普節點,保持統一概念.

而 Cluster 是外圍概念,所以 Cluster 的目的是將多個 Invoker 僞裝成一個 Invoker,這樣其它人只要關注 Protocol 層 Invoker 即可,加上 Cluster 或者去掉 Cluster 對其它層都不會造成影響,因爲只有一個提
供者時,是不需要 Cluster 的.

Proxy 層封裝了所有接口的透明化代理,而在其它層都以 Invoker 爲中心,只有到了暴露給用戶使用時,才用 Proxy 將 Invoker 轉成接口,或將接口實現轉成 Invoker,也就是去掉 Proxy 層 RPC 是可以 Run 的,只是不那麼透明,不那麼看起來像調本地服務一樣調遠程服務.

而 Remoting 實現是 Dubbo 協議的實現,如果你選擇 RMI 協議,整個 Remoting 都不會用上,Remoting 內部再劃爲 Transport 傳輸層和 Exchange 信息交換層,Transport 層只負責單向消息傳輸,是對 Mina, Netty, Grizzly 的抽象,它也可以擴展 UDP 傳輸,而 Exchange 層是在傳輸層之上封裝了 Request-Response 語義.

Registry 和 Monitor 實際上不算一層,而是一個獨立的節點,只是爲了全局概覽,用層的方式畫在一起.

  • dubbo-common
    公共邏輯模塊:包括 Util 類和通用模型.
    serialize 層放在 common 模塊中,以便更大程度複用.

  • dubbo-remoting
    遠程通訊模塊:相當於 Dubbo 協議的實現,如果 RPC 用 RMI協議則不需要使用此包.
    transport 層和 exchange 層都放在 remoting 模塊中,爲 rpc 調用的通訊基礎.
    Remoting 實現是 Dubbo 協議的實現,如果你選擇 RMI 協議,整個 Remoting 都不會用上,Remoting 內部再劃爲 Transport 傳輸層和 Exchange 信息交換層,
    Transport 層只負責單向消息傳輸,是對 Mina, Netty, Grizzly 的抽象,它也可以擴展 UDP 傳輸,而 Exchange 層是在傳輸層之上封裝了 Request-Response 語義.

  • dubbo-rpc
    遠程調用模塊:抽象各種協議,以及動態代理,只包含一對一的調用,不關心集羣的管理.
    protocol 層和 proxy 層都放在 rpc 模塊中,這兩層是 rpc 的核心,在不需要集羣也就是隻有一個提供者時,可以只使用這兩層完成 rpc 調用.

  • dubbo-cluster
    集羣模塊:將多個服務提供方僞裝爲一個提供方,包括:負載均衡, 容錯,路由等,集羣的地址列表可以是靜態配置的,也可以是由註冊中心下發.

  • dubbo-registry
    註冊中心模塊:基於註冊中心下發地址的集羣方式,以及對各種註冊中心的抽象.

  • dubbo-monitor
    監控模塊:統計服務調用次數,調用時間的,調用鏈跟蹤的服務.

  • dubbo-config
    配置模塊:是 Dubbo 對外的 API,用戶通過 Config 使用Dubbo,隱藏 Dubbo 所有細節.

  • dubbo-container
    容器模塊:是一個 Standlone 的容器,以簡單的 Main 加載 Spring 啓動,因爲服務通常不需要 Tomcat/JBoss 等 Web 容器的特性,沒必要用 Web 容器去加載服務.
    整體上按照分層結構進行分包,與分層的不同點在於:
    container 爲服務容器,用於部署運行服務,沒有在層中畫出.
    protocol 層和 proxy 層都放在 rpc 模塊中,這兩層是 rpc 的核心,在不需要集羣也就是隻有一個提供者時,可以只使用這兩層完成 rpc 調用.
    transport 層和 exchange 層都放在 remoting 模塊中,爲 rpc 調用的通訊基礎.
    serialize 層放在 common 模塊中,以便更大程度複用.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章