前言:在上一篇文章中我們介紹了如何去切換Ribbon的負載均衡模式,而本章節內容則是介紹Ribbon默認負載輪詢算法的原理。
1、負載輪詢算法公式
rest接口第N次請求數 % 服務器集群總數 = 實際調用服務器下標(每次服務器重啟后rest接口計數從1開始)
舉例子:
現在集群有兩臺服務器,分別有payment8001、payment8002這兩個實例,即服務器集群總數為2
把這兩個實例放進一個List集合里,即List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
如:List[0] instances = 127.0.0.1:8001
???????List[1] instances = 127.0.0.1:8002
之后對請求數進行%服務器集群總數的操作,然后取出實際調用的服務器下標,用該下標從實例集合里取出的實例就是要訪問的服務器
如:
第1次請求 : 1 % 2 = 1,即這時要調用List集合下標為1的服務器,獲得instances下標為1的服務器地址127.0.0.1:8002,然后調用這臺服務器
第2次請求 : 2 % 2 = 0,即這時要調用List集合下標為0的服務器,獲得instances下標為0的服務器地址127.0.0.1:8001,然后調用這臺服務器
第3次請求 : 3 % 2 = 1,即這時要調用List集合下標為1的服務器,獲得instances下標為1的服務器地址127.0.0.1:8002,然后調用這臺服務器
第4次請求 : 4 % 2 = 0,即這時要調用List集合下標為0的服務器,獲得instances下標為0的服務器地址127.0.0.1:8001,然后調用這臺服務器
第5次請求 : 5 % 2 = 1,即這時要調用List集合下標為0的服務器,獲得instances下標為1的服務器地址127.0.0.1:8002,然后調用這臺服務器
如此類推.......
以上就是Ribbon輪詢算法的原理
2、Ribbon負載輪詢算法源碼解析
(1)我們進入到MySelfRule這個類里面,然后點進IRule類
(2)點擊跳轉到IRule接口的RoundRobinRule實現類里,RoundRobinRule這個類就是關于輪詢算法的代碼實現
(3)解析源代碼
[1]我們可以看到RoundRobinRule構造方法里初始化了一個值為0的AtomicInteger類
[2]負載均衡算法主要實現在choose方法里,我們看choose方法可以看到關于各種關于服務的非空判斷和各種的取值,其中最重要的是通過incrementAndGetModulo方法取得下標,然后根據這個下標從服務集合里取出其中一個服務
[3]incrementAndGetModulo方法,它的實現方式就跟我們第一個步驟介紹的算法一樣,即:?
往incrementAndGetModulo方法傳入服務總數,nextServerCyclicCounter.get()方法取得原子類當前的值,因為默認值是0,所以取得的值是0,即current的值為0,(current + 1) % modulo的計算方式就跟我們第一個步驟說的一樣,即是請求次數%服務總數,current為0,module是服務總數,假使我們當前的服務有有payment8001、payment8002兩個,即module是2,(current + 1) % modulo求得next的值為1,nextServerCyclicCounter.compareAndSet(current, next))方法能比較AtomicInteger的值是否被其他線程改變了,若沒改變則把next的值更新到AtomicInteger里,如被改變了,則繼續下次循環,直到設置AtomicInteger值成功,把next的值返回為止,在不斷地調用choose方法時,會不斷地進行對AtomicInteger+1然后對服務總數求模取余的操作,然后不斷返回下標,不斷的返回相應下標的服務