整理自官網,對整體理解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 模塊中,以便更大程度複用.