高級JAVA開發 Dubbo部分

Dubbo

參考和摘自:
中華石杉 《Java工程師面試突擊第1季》
Dubbo 官網文檔

Dubbo架構&框架設計

架構
在這裏插入圖片描述
Dubbo 架構具有以下幾個特點,分別是連通性、健壯性、伸縮性、以及向未來架構的升級性。參考:架構

重點摘抄:

  1. 註冊中心和監控中心全部宕機,不影響已運行的提供者和消費者,消費者在本地緩存了提供者列表
  2. 註冊中心和監控中心都是可選的,服務消費者可以直連服務提供者
  3. 服務提供者全部宕掉後,服務消費者應用將無法使用,並無限次重連等待服務提供者恢復

框架設計

加上用戶實現的業務service,一共10層:

  1. service層(用戶實現):用戶實現接口提供服務
  2. config 配置層:對外配置接口,以 ServiceConfig, ReferenceConfig 爲中心,可以直接初始化配置類,也可以通過 spring 解析配置生成配置類
  3. proxy 服務代理層:服務接口透明代理,生成服務的客戶端 Stub 和服務器端 Skeleton, 以 ServiceProxy 爲中心,擴展接口爲 ProxyFactory
  4. registry 註冊中心層:封裝服務地址的註冊與發現,以服務 URL 爲中心,擴展接口爲 RegistryFactory, Registry, RegistryService
  5. cluster 路由層:封裝多個提供者的路由及負載均衡,並橋接註冊中心,以 Invoker 爲中心,擴展接口爲 Cluster, Directory, Router, LoadBalance
  6. monitor 監控層:RPC 調用次數和調用時間監控,以 Statistics 爲中心,擴展接口爲 MonitorFactory, Monitor, MonitorService
  7. protocol 遠程調用層:封裝 RPC 調用,以 Invocation, Result 爲中心,擴展接口爲 Protocol, Invoker, Exporter
  8. exchange 信息交換層:封裝請求響應模式,同步轉異步,以 Request, Response 爲中心,擴展接口爲 Exchanger, ExchangeChannel, ExchangeClient, ExchangeServer
  9. transport 網絡傳輸層:抽象 mina 和 netty 爲統一接口,以 Message 爲中心,擴展接口爲 Channel, Transporter, Client, Server, Codec
  10. serialize 數據序列化層:可複用的一些工具,擴展接口爲 Serialization, ObjectInput, ObjectOutput, ThreadPool

Dubbo的網絡通信協議&序列化

網絡通信協議不同,在各場景下性能不同。dubbo協議採用單鏈接長鏈接,適合頻繁小數據包傳輸,不適合大數據包傳輸(會一直佔用IO通道)。單鏈接的好處就是減少了頻繁創建鏈接時不得不做出的額外消耗(握手驗證 等)。並使用異步 IO,複用線程池,防止 C10K 問題。以下介紹不同協議適合的場景。

協議參考手冊

協議 連接個數 連接方式 傳輸協議 傳輸方式 序列化 適用範圍 適用場景
dubbo(缺省 單連接 長連接 TCP NIO 異步傳輸 Hessian 二進制序列化 - 傳入傳出參數數據包較小(建議小於100K)
- 消費者比提供者個數多,單一消費者無法壓滿提供者
- 儘量不要用 dubbo 協議傳輸大文件或超大字符串
常規遠程服務方法調用
rmi 多連接 短連接 TCP 同步傳輸 Java 標準二進制序列化 - 傳入傳出參數數據包大小混合
- 消費者與提供者個數差不多
- 可傳文件
常規遠程服務方法調用,與原生RMI服務互操作
hessian 多連接 短連接 HTTP 同步傳輸 Hessian二進制序列化 - 傳入傳出參數數據包較大
- 提供者比消費者個數多,提供者壓力較大
- 可傳文件
頁面傳輸,文件傳輸,或與原生hessian服務互操作
http 多連接 短連接 HTTP 同步傳輸 表單序列化 - 傳入傳出參數數據包大小混合
- 提供者比消費者個數多
- 可用瀏覽器查看,可用表單或URL傳入參數
- 暫不支持傳文件
需同時給應用程序和瀏覽器 JS 使用的服務。
webservice 多連接 短連接 HTTP 同步傳輸 SOAP 文本序列化 系統集成,跨語言調用
thrift
memcached
redis
rest

序列化框架優缺點:

優點 缺點
Kryo 速度快,序列化後體積小 跨語言支持較複雜
Hessian 默認支持跨語言 較慢
Protostuff 速度快,基於protobuf 需靜態編譯
Protostuff-Runtime 無需靜態編譯,但序列化前需預先傳入schema 不支持無默認構造函數的類,反序列化時需用戶自己初始化序列化後的對象,其只負責將該對象進行賦值
Java 使用方便,可序列化所有類 速度慢,佔空間

引自:序列化框架性能對比(kryo、hessian、java、protostuff)

負載均衡策略

缺省爲 random 隨機調用。

  • Random LoadBalance
    隨機,按權重設置隨機概率。
    在一個截面上碰撞的概率高,但調用量越大分佈越均勻,而且按概率使用權重後也比較均勻,有利於動態調整提供者權重。
  • RoundRobin LoadBalance
    輪詢,按公約後的權重設置輪詢比率。
    存在慢的提供者累積請求的問題,比如:第二臺機器很慢,但沒掛,當請求調到第二臺時就卡在那,久而久之,所有請求都卡在調到第二臺上。
  • LeastActive LoadBalance
    最少活躍調用數,相同活躍數的隨機,活躍數指調用前後計數差。
    使慢的提供者收到更少請求,因爲越慢的提供者的調用前後計數差會越大。
  • ConsistentHash LoadBalance
    一致性 Hash,相同參數的請求總是發到同一提供者。
    當某一臺提供者掛時,原本發往該提供者的請求,基於虛擬節點,平攤到其它提供者,不會引起劇烈變動。
    算法參見:http://en.wikipedia.org/wiki/Consistent_hashing
    缺省只對第一個參數 Hash,如果要修改,請配置 <dubbo:parameter key=“hash.arguments” value=“0,1” />
    缺省用 160 份虛擬節點,如果要修改,請配置 <dubbo:parameter key=“hash.nodes” value=“320” />

參見官方 負載均衡

集羣容錯

缺省爲 failover 重試

  • Failover Cluster
    失敗自動切換,當出現失敗,重試其它服務器 。通常用於讀操作,但重試會帶來更長延遲。可通過 retries=“2” 來設置重試次數(不含第一次)。
  • Failfast Cluster
    快速失敗,只發起一次調用,失敗立即報錯。通常用於非冪等性的寫操作,比如新增記錄。
  • Failsafe Cluster
    失敗安全,出現異常時,直接忽略。通常用於寫入審計日誌等操作。
  • Failback Cluster
    失敗自動恢復,後臺記錄失敗請求,定時重發。通常用於消息通知操作。
  • Forking Cluster
    並行調用多個服務器,只要一個成功即返回。通常用於實時性要求較高的讀操作,但需要浪費更多服務資源。可通過 forks=“2” 來設置最大並行數。
  • Broadcast Cluster
    廣播調用所有提供者,逐個調用,任意一臺報錯則報錯 [2]。通常用於通知所有提供者更新緩存或日誌等本地資源信息。

參見官方 集羣容錯

Dubbo SPI(Service Provider Interface)& Dubbo的Filter

官方:DubboSPI
總結:Dubbo 並未使用 Java SPI,而是重新實現了一套功能更強的 SPI 機制。
兩者在使用上最大的區別是Java SPI配置多實現出來的是個列表,Dubbo SPI配置出來的是個字典(鍵值對)。在框架中使用:在接口上註解@SPI(“keyName”),keyName即爲實現類key,dubbo自己的jar包的/META-INF/dubbo/internal/下尋找實現類配置後加載實現類。

替換動態代理示例:

# 添加如下JavassistProxyFactory 實現類:
 public class MyselfJavassistProxyFactory extends JavassistProxyFactory {
    public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
        return (T) Proxy.getProxy(interfaces).newInstance(new SevenMinInvokerInvocationHandler(invoker));
    }
    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
        return super.getInvoker(proxy, type, url);
    }
 }
# /META-INF/dubbo/com.alibaba.dubbo.rpc.ProxyFactory 配置如下:
 myselfJavassistProxyFactory=com.example.dubbo.rpc.proxy.javassist.MyselfJavassistProxyFactory
# dubbo.xml 配置如下:
 <dubbo:consumer timeout="8000" proxy="myselfJavassistProxyFactory"/>

利用Dubbo SPI取得實現類實例:在這裏插入圖片描述
另外,(服務提供方和服務消費方)Protocol層設置了調用過程攔截(Filter),Dubbo 本身的大多功能均基於此擴展點實現,每次遠程方法執行,該攔截都會被執行,擴展時請注意對性能的影響。
在這裏插入圖片描述
可用SPI機制配置com.alibaba.dubbo.rpc.Filter實現類,並配置到框架Filter中去。
參見:
調用攔截擴展
Dubbo的Filter鏈梳理

這裏有一個利用Filter在Dubbo集成hystrix的例子可以參考:
dubbo-hystrix-support

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