Java開發瓶頸,Dubbo架構學習整理

  • 條件路由規則:基於條件的路由規則,例如:host = 10.20.153.10 => hsot = 10.20.153.11。=>之前是consumer匹配條件,所有參數和consumer的URL進行對比,如果consumer滿足匹配條件,則對consumer執行後面的過濾規則。=>之後是provider地址列表的過濾條件,所有參數和provider的URL進行對比,consumer只拿到過濾後的地址列表
  • 4. 負載均衡

    如上圖 LoadBlance 模塊所示:在集群負載均衡時,Dubbo提供了不同的策略:

    • Random【默認】:隨機,按權重設置隨機概率。調用量越大越均勻,有利於動態調整權重
    • RoundRobin:輪詢,按公約後的權限設置輪詢比率。如果有臺機器很慢,但沒掛,當請求到那一臺時就卡在那兒,久而久之,所有請求都卡在那臺機器上
    • LeastActive:最少活躍調用數,活躍數指調用前後計數差,越慢的provider的調用前後計數差越大,使得慢的provider收到更少請求
    • ConsistentHash:一致性Hash,相同參數的請求發往同一臺provider,當一臺provider掛掉時,原本發往該機器的請求,基於虛擬節點會平攤到其他機器,不會引起劇烈變動

    5. 線程派發模型

    Java開發瓶頸,Dubbo架構學習整理

    如果事件處理的邏輯能迅速完成,並且不發生新的IO請求(例如在內存中記個標識),則在IO線程上處理更快,因為減少了線程池調度

    如果事件處理的邏輯較慢,或需要發起新的IO請求(例如需要查詢數據庫),則必須派發到線程池,否則 IO 線程阻塞,將導致不能接受其他請求

    因此需要不同的派發策略和不同的線程池組合來應對不同的場景:

    Dispatcher:

    • all:所有消息派發到 ThreadPool,包括請求、響應、連接事件、斷開事件、心跳等
    • direct:所有消息不派發 ThreadPool,全在 IO 線程上執行
    • message:只有請求響應消息派發到 ThreadPool,其他連接事件、斷開事件、心跳等,在 IO 線程上執行
    • execution:只請求消息派發到 ThreadPool,其他事件包括響應事件、連接斷開事件、心跳等消息,在 IO 線程上執行
    • connection:在 IO 線程上,將連接斷開事件放入隊列,有序逐個執行,其他時間派發到 ThreadPool

    ThreadPool:

    • fixed【默認】:固定大小線程池,啟動時建立線程,一直持有不關閉
    • cached:緩存線程池,空閒一分鐘自動刪除,需要時重建
    • limited:可伸縮線程池,線程數只增長不收縮,目的是為了避免收縮時大流量引起的性能問題
    • eager:優先創建Worker線程池,corePoolSize < 任務數量 < maximumPoolSize時,優先創建 Worker 處理任務。任務數量 > maximumPoolSize時,任務放入阻塞隊列中,阻塞隊列充滿時拋出 RejectExecutionException

    6. 上下文信息和隱式參數

    上下文中存放著當前調用過程中所需的環境信息。RpcContext 是一個 ThreadLocal 的臨時狀態記錄器,當接收或發起 RPC 請求時,RpcContext 都會發生變化。比如:A調用B,B調用C,在B調C之前,B機器上 RpcContext 記錄的是A調用B的信息。

    通過 RpcContext 的 setAttachment 和 getAttachment 可以在 provider 和 consumer 之間進行參數的隱式傳遞

    Java開發瓶頸,Dubbo架構學習整理

    7. 異步調用

    基於NIO的非阻塞實現並行調用,客戶端不需要啟動多線程即可完成多個遠程服務的並行調用,相對比多線程開銷較小

    Java開發瓶頸,Dubbo架構學習整理

    8. 註冊中心

    對於 provider,它需要發佈服務,而且由於應用系統的複雜性,服務的數量、類型也不斷膨脹;對於 consumer,它最關心如何獲取到它所需要的服務,而面對複雜的應用系統,需要管理大量的服務調用

    服務註冊中心通過特性協議將服務統一管理起來,有效的優化內部應用對服務發佈/使用的流程。Dubbo提供的註冊中心有如下幾種類型可供選擇:

    ① ZooKeeper註冊中心

    Java開發瓶頸,Dubbo架構學習整理

    ZK是一個樹形的服務目錄,支持變更推送,適合作為Dubbo服務的註冊中心。流程如下:

    • provider啟動時,向 /dubbo/com.foo.BarService/providers 目錄下寫入自己的 URL 地址
    • consumer啟動時,訂閱 /dubbo/com.foo.BarService/providers 目錄下的 providers 地址,並向 /dubbo/com.foo.BarService/consumers 目錄下寫入自己的 URL 地址
    • 監控中心啟動時,訂閱 /dubbo/com.foo.BarService 目錄下的所有 provider 和 consumer URL地址

    當 provider 出現斷電等異常停機時,註冊中心能自動刪除 provider 信息。當註冊中心重啟、或會話過期時,能自動恢復註冊數據和訂閱請求

    ② Multicase註冊中心

    Java開發瓶頸,Dubbo架構學習整理

    Multicast註冊中心不需要啟動任何中心節點,只要廣播地址即可互相發現

    • provider 啟動時廣播自己的地址
    • consumer 啟動時廣播訂閱請求
    • provider 收到訂閱請求時,單播自己的地址給訂閱者,若設置了 unicast=false,則廣播給訂閱者
    • consumer 收到 provider 地址時,連接地址進行 RPC 調用

    組播受網絡結構限制,只適合小規模應用或開發階段

    ③ Redis註冊中心

    Java開發瓶頸,Dubbo架構學習整理

    使用 redis 的 Key/Map 結構存儲數據結構:

    • 主 Key 為服務名和類型
    • Map 中的 Key 為 URL 地址
    • Map 中的 Value 為過期時間,用於判斷髒數據,髒數據由監控中心刪除

    調用過程:

    1. provider 啟動時,向 Key:/dubbo/com.foo.BarService/providers 下,添加當前 provider 的地址
    2. 並向 Channel:/dubbo/com.foo.BarService/providers 發送 register 事件
    3. consumer 啟動時,向 Key:/dubbo/com.foo.BarService/providers 下,添加當前 consumer 的地址
    4. 並從 Channel:/dubbo/com.foo.BarService/providers 訂閱 register 和 unregister 事件
    5. consumer 收到 register 和 unregister 事件後,從 Key:/dubbo/com.foo.BarService/providers 下獲取 provider 地址列表
    6. 服務監控中心啟動時,從 Channel:/dubbo/* 訂閱 register 和 unregister,以及 subscribe 和 unsubscribe 事件
    7. 監控中心收到 register 和 unregister 事件後,從 Key:/dubbo/com.foo.BarService/providers 下獲取 provider 地址列表
    8. 監控中心收到 subscribe 和 unsubscribe 事件後,從 Key:/dubbo/com.foo.BarService/comsumers 下獲取 consumer 地址列表


    分享到:


    相關文章: