
服務提供者在啟動的時候,向zk上的/dubbo/${serviceName}/providers目錄下寫下自己的URL位址
- dubbo會先調用checkAndUpdateSubConfigs方法檢查配置是否合理,如果合理再調用doExportUrlsFor1Protocol方法通過配置組裝URL,然後調用doExportUrl方法進行服務暴露
注:注冊中心
- 用戶端會先檢查配置是否合理,然後建立RegisterDirectory執行個體,生成服務消費者連結向注冊中心注冊,然後訂閱providers,configurators,routers節點下的資料
- 由于一個服務可能部署在多台伺服器上,這樣就會在 providers 産生多個節點,這個時候就需要 Cluster 将多個服務節點合并為一個,并生成一個 Invoker。
Zookeeper:
- 分布式協調和通知:不同的用戶端都對Zookeeper上的同一個資料節點進行Watcher注冊,監聽資料節點的變化。若資料節點發生變化,那麼所有訂閱的用戶端都能夠接收到相應的Watcher通知,并作出相應處理。
2)叢集管理:
a.用戶端如果對Zookeeper的資料節點注冊Watcher監聽,那麼當該資料及诶單内容或是其子節點清單發生變更時,Zookeeper伺服器就會向訂閱的用戶端發送變更通知。b. 對在Zookeeper上建立的臨時節點,一旦用戶端與伺服器之間的會話失效,那麼臨時節點也會被自動删除。
3)負載均衡:com.alibaba.dubbo.rpc.cluster.LoadBalance類
Random LoadBalance(預設使用)
- 随機,按權重設定随機機率。
- 在一個截面上碰撞的機率高,但調用量越大分布越均勻,而且按機率使用權重後也比較均勻,有利于動态調整提供者權重。
- 看方法的細節就是首先周遊每個提供服務的機器,擷取每個服務的權重,然後累權重重值,判斷每個服務的提供者權重是否相同,如果每個調用者的權重不相同,并且每個權重大于0,那麼就會根據權重的總值生成一個随機數,再用這個随機數,根據調用者的數量每次減去調用者的權重,直到計算出目前的服務提供者随機數小于0,就選擇那個提供者!另外,如果每個機器的權重的都相同,那麼權重就不會參與計算,直接選擇随機算法生成的某一個選擇,完全随機。可以看出,随機調用法,
RoundRobin LoadBalance
- 輪詢,按公約後的權重設定輪詢比率。
- 存在慢的提供者類即請求問題,比如:第二台機器很慢,但沒挂,當請求調到第二台時就卡在那,久而久之,所有請求都卡在調到第二台上。
- 輪詢調用,輪詢調用的過程主要是維護了局部變量的一個LinkdesHashMap(有順序的Map)去存儲調用者和權重值的對應關系,然後周遊每個調用者,把調用者和目前大于0的權重值放進去,再累權重重值。還有一個全局變量的map,找到第一個服務調用者,首先是找到每個服務的key值和method,這裡可以了解為辨別第一個調用者的唯一key,然後再給它對應的值保證原子性的+1(AtomicPositiveInteger是原子的),再對這個值取模總權重,再每次對其權重值-1,知道它取模與總權重值等于0就選擇該調用者,可以稱之為"降級取模"(隻是一種的計算層面,而不是真正降級)。總結:輪詢調用并不是簡單的一個接着一個依次調用,它是根據權重的值進行循環的。
LeastActive LoadBalance
- 最少活躍調用數,相同活躍數的随機,活躍數指調用前後計數差。
- 使慢的提供者收到更少請求,因為越慢的提供者的調用前後計數差會越大。
- 最少活躍數調用法:這個方法的主要作用根據服務的提供者的運作狀态去選擇伺服器,主要的思路就是周遊每個調用者,然後擷取每個伺服器的運作狀态,如果目前運作的運作狀态小于最小的狀态-1,把它儲存在leastIndexs中的第一個位置,并且認定所有的調用者權重都相同,然後直接傳回那個調用者(這裡的邏輯是:找到最少活躍數(在代碼層反應就是:active的值))。如果計算出的權重值和最少的權重值相同,那麼把它儲存在leastIndexs數組裡面,累權重重值,如果目前的權重值不等于初始值firstWeight,那麼就認定不是所有的調用者的權重不同。然後再周遊lestIndexs,取權重累加值的随機數生成權重偏移量,在累減它,到它小于0的時候傳回那個調用者。如果這些都不符合,就從leastIndexs随機選一個index,傳回那個調用者!
ConsistentHash LoadBalance
- 一緻性Hash,相同參數的請求總是發到同一提供者。
- 當某一台提供者挂時,原本發往該提供者的請求,基于虛拟節點,平攤到其他提供者,不會引起劇烈變動。
- 注意排程政策:
Dispatch
所有的sent事件方法、心跳請求全部在IO線程上執行。
1、all : 除sent事件回調方法、心跳外,全部線上程池上執行。
2、execution : 與all類似,唯一區就是all線上程池未指定時,可以使用共享線程池,這個差别等同于沒有。
3、 message : 隻有請求事件線上程池中執行,其他在IO線程上執行。
4、connection : 請求事件線上程池中執行,連接配接、斷開連接配接事件排隊執行(含一個線程的線程池)
5、direct : 所有事件都在IO線程中執行。