自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

自古帝王多短命,假如皇帝也懂負載均衡算法...

原創(chuàng)
開發(fā) 架構(gòu) 開發(fā)工具 算法
大家都知道古代皇帝各個都是后宮佳麗三千,而皇帝身上都天然的帶著雨露均沾的精神,不想單獨的寵愛一人!

【51CTO.com原創(chuàng)稿件】大家都知道古代皇帝各個都是后宮佳麗三千,而皇帝身上都天然的帶著雨露均沾的精神,不想單獨的寵愛一人!

[[313028]]

 

圖片來自 Pexels

弱水三千,又怎舍得只取一瓢飲?據(jù)傳皇帝們晚上睡覺個個都怕冷,因此每晚都需要有人侍寢,那么這么多后宮,該翻誰牌子、怎么分配侍寢名額呢?

還別說,皇帝行房事竟還挺講究的!早在《春秋》就有記載“晦陰惑疾,明謠心疾,以辟六氣”。

九嬪以下,每九人中進御一人,八十一女御占九個晚上,世婦二十七人占三個晚上,九嬪占一個晚上,三夫人占一個晚上,以上共十四夜,皇后獨占一個晚上,共十五夜。上半個月按上述安排進御,下半個月從十六日開始,由皇后起,再御九嬪、世婦、女御,與月亮由盛而衰相對應......

不同朝代的皇帝也有不同寵幸妃子的方法,著名的有羊車望幸、擲篩侍寢、蝶幸、翻牌懸燈等等。

不過在我看來,如果皇帝懂負載均衡算法的話,大可不必這么折騰,一套算法便可搞定終身侍寢大事!因此我們今天來介紹幾種常用的負載均衡算法及代碼實現(xiàn)!

先看下文章的大綱:

  • 輪詢算法
  • 加權(quán)輪詢算法
  • 隨機算法
  • 加權(quán)隨機算法
  • 源地址 hash 算法
  • 一致性 hash 算法

輪詢算法

據(jù)史料記載,乾隆一生妃嬪就有 42 人,還不算大明湖畔的夏雨荷等在下江南時候留下的情。

[[313029]]

 

假設在某個時期內(nèi),皇阿瑪最寵幸的有令妃、嫻妃、高貴妃、純妃四位。那普通的輪詢算法怎么去選擇呢?

我們先定義一個妃子集合如下:

  1. /** 
  2.  * *所有妃子集合 
  3.  */ 
  4. public static final List<String> PRINCESS_LIST = Arrays.asList("令妃""嫻妃""高貴妃""純妃"); 

然后從列表中輪詢侍寢的妃子,用一個變量 index 去記錄輪詢的位置。

  1. // 記錄循環(huán)的位置 
  2. private static Integer index = 0; 
  3. public static void main(String[] args) { 
  4.     for (int i = 0; i < 10; i++) { 
  5.         System.out.println(getPrincess()); 
  6.     } 
  7. private static String getPrincess() { 
  8.     // 超過數(shù)組大小需要歸零(每次獲取前判斷,防止配置變化導致索引越界) 
  9.     if (index >= PrincessConfig.PRINCESS_LIST.size()) { 
  10.         index = 0; 
  11.     } 
  12.     String princess = PrincessConfig.PRINCESS_LIST.get(index); 
  13.     index++; 
  14.     return princess; 

輸出結(jié)果就不貼出來了。該算法的特點就是簡單、簡單、簡單!但是也存在很大缺點!

如果皇帝更寵愛令妃,想讓她侍寢的概率更高呢?那就需要用到下面的加權(quán)輪詢算法!

加權(quán)輪詢算法

加權(quán)輪詢就是可以主觀的給每個妃子設置一個喜好值(權(quán)重值),以控制被選中的概率,因此我們需要定義如下的配置:

  1. /** 
  2.  * *所有妃子集合 
  3.  */ 
  4. public static final Map<String, Integer> PRINCESS_MAP = new LinkedHashMap<String, Integer>() { 
  5.     { 
  6.         put("令妃", 5); 
  7.         put("嫻妃", 1); 
  8.         put("高貴妃", 3); 
  9.         put("純妃", 2); 
  10.     } 
  11. }; 

這里的配置就不再是簡單的一個集合,每個妃子都對應了一個權(quán)重值,那輪詢的時候怎么根據(jù)這個值去提高被選中的概率呢?

下面我們來講三種比較常見的實現(xiàn)。

加權(quán)輪詢實現(xiàn)一

我們的思路是把這個 map 的 key(妃子)根據(jù)權(quán)重值轉(zhuǎn)存到一個 list 中,然后再去輪詢這個 list,如果權(quán)重值為 5,那就在 list 中添加 5 條相同的記錄!

然后我們?nèi)ケ闅v這個 list,這樣權(quán)重值越高,在 list 中出現(xiàn)的概率就越高,被輪詢中的概率也就越高!

  1. // 記錄循環(huán)的位置 
  2. private static Integer index = 0; 
  3.  
  4. public static void main(String[] args) { 
  5.    for (int i = 0; i < 11; i++) { 
  6.        System.out.println(getPrincess1()); 
  7.   } 
  8.  
  9. private static String getPrincess1() { 
  10.  
  11.    // 遍歷map放入到list中 
  12.    List<String> princessList = new ArrayList<String>(); 
  13.    for (String princess : PrincessConfig.PRINCESS_MAP.keySet()) { 
  14.        int weight = PrincessConfig.PRINCESS_MAP.get(princess); 
  15.        // 根據(jù)權(quán)重值重復放入到一個list中 
  16.        for (int i = 0; i < weight; i++) { 
  17.            princessList.add(princess); 
  18.       } 
  19.   } 
  20.  
  21.    if (index >= princessList.size()) { 
  22.        index = 0; 
  23.   } 
  24.    String princess = princessList.get(index); 
  25.  
  26.    index++; 
  27.  
  28.    return princess; 

輸出結(jié)果如下:

 

該加權(quán)輪詢算法比較簡單,比較容易實現(xiàn)。但是也有個問題,我們配置的權(quán)重值是 5、1、3、2,那我們是不是也可以配置成 50、10、30、20 呢?

那按照上面的方式,我們是不是就需要把同樣的元素往 list 里面放幾百個呢?這顯然是比較不合理且耗內(nèi)存的!

加權(quán)輪詢實現(xiàn)二

基于上面的算法存在的問題,我們考慮用類似占比的方式來處理。

比如我們配置的權(quán)重值為 50、10、30、20,那在橫坐標上表示就是 0_____50_60__80__110。

我們還是用一個 index 去記錄輪詢的位置,如果 index 在 0~50 之間就代表第一個妃子被選中,如果在 50~60 之間就代表第二個妃子被選中......

我們看具體代碼實現(xiàn):

  1. // 記錄循環(huán)的位置 
  2. private static Integer indexInteger = 0; 
  3.  
  4. public static void main(String[] args) { 
  5.    for (int i = 0; i < 11; i++) { 
  6.        System.out.println(getPrincess2()); 
  7.   } 
  8.  
  9. private static String getPrincess2() { 
  10.    //記錄總權(quán)重值 
  11.    int totalWeight = 0; 
  12.    for (String princess : PrincessConfig.PRINCESS_MAP.keySet()) { 
  13.        int weight = PrincessConfig.PRINCESS_MAP.get(princess); 
  14.        totalWeight += weight; 
  15.   } 
  16.  
  17.    // 歸零 
  18.    if (indexInteger >= totalWeight) { 
  19.        indexInteger = 0; 
  20.   } 
  21.  
  22.    int index = indexInteger; 
  23.    String result = null
  24.    for (String princess : PrincessConfig.PRINCESS_MAP.keySet()) { 
  25.        int weight = PrincessConfig.PRINCESS_MAP.get(princess); 
  26.  
  27.        // 落在當前區(qū)間 直接返回 
  28.        if (index < weight) { 
  29.  
  30.            result = princess; 
  31.            break; 
  32.       } 
  33.  
  34.        // 沒有落在當前區(qū)間 繼續(xù)循環(huán) 
  35.        index = index - weight; 
  36.  
  37.   } 
  38.  
  39.    indexInteger++; 
  40.    return result; 

輸出結(jié)果與上面的方法一毛一樣:

 

該加權(quán)輪詢算法略復雜于第一種,但是這兩種實現(xiàn)都存在的共同問題是,按照我們目前的配置去輪詢會連續(xù) 5 次令妃、再 1 次嫻妃、再 3 次高貴妃......

連續(xù) 5 次!就算皇阿瑪再喜歡令妃,怕是令妃也有點吃不消!用計算機術(shù)語說也就是負載不是很均衡!

加權(quán)輪詢實現(xiàn)三(平滑加權(quán)輪詢)

平滑加權(quán)輪詢算法就是為了解決上面負載不均衡的情況的,該算法實現(xiàn)起來相對比較復雜!

每個妃子不僅有一個權(quán)重值(weight),還有一個會變化的動態(tài)權(quán)重值(dynamicWeight)來輔助計算。

動態(tài)權(quán)重值計算邏輯如下:

  • 動態(tài)權(quán)重值 dynamicWeight 初始為 0。
  • 每次獲取輪詢獲取目標妃子時先設置 dynamicWeight=dynamicWeight+weight。
  • 然后找到所有妃子中動態(tài)權(quán)重值 dynamicWeight 最大的一個,則為本次輪詢到的目標。
  • 將本次輪詢到的目標的 dynamicWeight 設置為 dynamicWeight-totalWeight(總權(quán)重值)。

這樣看可能會有點不是很明白,我們來做個推算,假設我們還是有如下配置(配置中只有妃子名稱及對應的權(quán)重值):

  1. /** 
  2.  * *所有妃子集合 
  3.  */ 
  4. public static final Map<String, Integer> PRINCESS_MAP = new LinkedHashMap<String, Integer>() { 
  5.     { 
  6.         put("令妃", 5); 
  7.         put("嫻妃", 1); 
  8.         put("高貴妃", 3); 
  9.         put("純妃", 2); 
  10.     } 
  11. }; 

在上面的配置中總權(quán)重值 totalWeight=5+1+3+2 等于 11。

①按照上面算法的第一點,在第一次輪詢目標之前她們的 dynamicWeight 都是0。

因此四位妃子的 weight 和 dynamicWeight 值如下:

 

②按照上面算法的第二點,在第一次輪詢選中目標的時候 dynamicWeight=dynamicWeight+weight。

變化后四位妃子的 weight 和 dynamicWeight 值如下:

 

③按照上面算法的第三點,然后找最大的 dynamicWeight,也就是 5,因此第一次輪詢選中的就是令妃。

④按照上面算法的第四點,令妃的 dynamicWeight 需要減去 totalWeight。

變化后四位妃子的 weight 和 dynamicWeight 值如下:

 

然后第二次輪詢的時候又需要按照算法的第一點設置 dynamicWeight。

設置后四位妃子的 weight 和 dynamicWeight 值如下:

 

就這樣一直按照算法處理下去,輪詢完 11 次后,所有妃子的 dynamicWeight 又會全部變?yōu)?0......

如果大家依然還是有點模糊,我們只能上代碼為敬了!我們需要先定義一個實體,來存放每個妃子及對應的 weight 及 dynamicWeight 屬性:

  1. /** 
  2.  * *權(quán)重實體 
  3.  *  
  4.  * @author sullivan 
  5.  * 
  6.  */ 
  7. public class PrincessWeight { 
  8.     private String princess; 
  9.     private Integer weight; 
  10.     private Integer dynamicWeight; 
  11.     public PrincessWeight(String princess, Integer weight, Integer dynamicWeight) { 
  12.         super(); 
  13.         this.princess = princess; 
  14.         this.weight = weight; 
  15.         this.dynamicWeight = dynamicWeight; 
  16.     } 

然后定義兩個全局的對象存放對象:

  1. // 每個妃子及對應的權(quán)重實體 
  2. private static Map<String, PrincessWeight> weightMap = new HashMap<String, PrincessWeight>(); 
  3. // 總權(quán)重值 
  4. private static int totalWeight = 0; 

再進行算法的實現(xiàn):

  1. private static String getPrincess() {     
  2.     // 初始化妃子及對應的權(quán)重實體 
  3.     if (weightMap.isEmpty()) { 
  4.         //將配置初始化到map中去 
  5.         for (String princess : PrincessConfig.PRINCESS_MAP.keySet()) { 
  6.             // 算法的第一點:初始dynamicWeight為0 
  7.             weightMap.put(princess, new PrincessWeight(princess, PrincessConfig.PRINCESS_MAP.get(princess), 0)); 
  8.             totalWeight += PrincessConfig.PRINCESS_MAP.get(princess); 
  9.         } 
  10.     } 
  11.  
  12.     // 算法的第二點:設置currentWeight=設置weight+currentWeight 
  13.     for (PrincessWeight weight : weightMap.values()) { 
  14.         weight.setDynamicWeight(weight.getWeight() + weight.getDynamicWeight()); 
  15.     } 
  16.  
  17.     // 算法的第三點:尋找最大的currentWeight 
  18.     PrincessWeight maxPrincessWeight = null
  19.     for (PrincessWeight weight : weightMap.values()) { 
  20.         if (maxPrincessWeight == null || weight.getDynamicWeight() > maxPrincessWeight.getDynamicWeight()) { 
  21.             maxPrincessWeight = weight; 
  22.         } 
  23.     } 
  24.  
  25.     // 算法的第四點:最大的dynamicWeight = dynamicWeight-totalWeight 
  26.     maxPrincessWeight.setDynamicWeight(maxPrincessWeight.getDynamicWeight() - totalWeight); 
  27.  
  28.     return maxPrincessWeight.getPrincess(); 

最終輸出如下:

 

這樣經(jīng)過 11 次輪詢,令妃同樣出現(xiàn)了 5 次,但是明顯不會再像之前算法那樣連續(xù)出現(xiàn)了,會均衡得多!!!如果還有不清楚的,可以去文末的 Github 地址上下載代碼自己調(diào)試及理解!

隨機算法

平滑加權(quán)輪詢算法能很好的進行負載了!但是皇阿瑪又說了,按照輪詢算法,我自己都能夠推出來每晚侍寢的妃子,不刺激不刺激。

皇帝嘛,總喜歡來些新鮮的刺激的我們也可以理解!還好我們有隨機算法可以解決,每晚都是隨機選一個,讓皇帝無法提前推測,給皇帝足夠的刺激感!

我們依然先定義一個妃子集合如下:

  1. /** 
  2.  * *所有妃子集合 
  3.  */ 
  4. public static final List<String> PRINCESS_LIST = Arrays.asList("令妃""嫻妃""高貴妃""純妃"); 

然后利用隨機函數(shù)去選擇一個目標:

  1. public static void main(String[] args) { 
  2.     for (int i = 0; i < 10; i++) { 
  3.         System.out.println(getPrincess()); 
  4.     } 
  5. /** 
  6.  * *隨機獲取侍寢妃子 
  7.  * @return 
  8.  */ 
  9. private static String getPrincess() { 
  10.     SecureRandom rd = new SecureRandom(); 
  11.     int index = rd.nextInt(PrincessConfig.PRINCESS_LIST.size()); 
  12.     return PrincessConfig.PRINCESS_LIST.get(index); 

因為輸出是隨機的,所以這里就不貼出來了。如果明白了輪詢算法,隨機算法理解起來也就簡單了,只是在輪詢中用一個全局的 index 去保存每次循環(huán)的位置,而在隨機中是每次去隨機出來一個值。

加權(quán)隨機算法

加權(quán)隨機實現(xiàn)一

加權(quán)隨機實現(xiàn)一與上面的加權(quán)輪詢實現(xiàn)一的思路幾乎一毛一樣,這里就直接上代碼了:

  1. public static void main(String[] args) { 
  2.         for (int i = 0; i < 10; i++) { 
  3.             System.out.println(getPrincess()); 
  4.         } 
  5.     } 
  6. private static String getPrincess() { 
  7.     List<String> princessList = new ArrayList<String>(); 
  8.     for (String princess : PrincessConfig.PRINCESS_MAP.keySet()) { 
  9.         int weight = PrincessConfig.PRINCESS_MAP.get(princess); 
  10.         for (int i = 0; i < weight; i++) { 
  11.             princessList.add(princess); 
  12.         } 
  13.     } 
  14.     Random rd = new Random(); 
  15.     int index = rd.nextInt(princessList.size()); 
  16.     return princessList.get(index); 

加權(quán)隨機實現(xiàn)二

加權(quán)隨機實現(xiàn)二與上面的加權(quán)輪詢實現(xiàn)二的思路幾乎一模一樣,這里也就直接上代碼了:

  1. public static void main(String[] args) { 
  2.     for (int i = 0; i < 10; i++) { 
  3.         System.out.println(getPrincess2()); 
  4.     } 
  5.  
  6. private static String getPrincess2() { 
  7.  
  8.     List<String> princessList = new ArrayList<String>(); 
  9.     int totalWeight = 0; 
  10.     for (String princess : PrincessConfig.PRINCESS_MAP.keySet()) { 
  11.         int weight = PrincessConfig.PRINCESS_MAP.get(princess); 
  12.         totalWeight += weight; 
  13.         for (int i = 0; i < weight; i++) { 
  14.             princessList.add(princess); 
  15.         } 
  16.     } 
  17.  
  18.     Random rd = new Random(); 
  19.     int index = rd.nextInt(totalWeight); 
  20.  
  21.     String result = null
  22.     for (String princess : PrincessConfig.PRINCESS_MAP.keySet()) { 
  23.         int weight = PrincessConfig.PRINCESS_MAP.get(princess); 
  24.  
  25.         // 落在當前區(qū)間 直接返回 
  26.         if (index < weight) { 
  27.  
  28.             result = princess; 
  29.             break; 
  30.         } 
  31.  
  32.         // 沒有落在當前區(qū)間 繼續(xù)循環(huán) 
  33.         index = index - weight; 
  34.  
  35.     } 
  36.     return result; 

源地址 hash 算法

我們的工作中開發(fā)系統(tǒng)很常見的一個需求就是需要登錄后才能訪問,這就會涉及到 session!

如果我們沒有做 session 共享,那登錄后的 session 信息只會存在我們調(diào)用登錄接口的那臺服務器上!

按照前面的輪詢算法或者隨機算法,我們同一客戶端的多次請求就會落在不同的服務器上,這樣就會導致部分接口沒權(quán)限訪問!

因此我們需要同一個客戶端多次的請求落在同一臺服務器上,這里常見的一種做法是對源地址進行 hash!

到這里我們也得讓我們的皇阿瑪歇會兒了,回到我們正常的業(yè)務場景中。假如我們有服務器配置如下:

  1. /** 
  2.      * *所有服務器集合 
  3.      */ 
  4.     public static final List<String> SERVER_IP_LIST = Arrays.asList( 
  5.         "192.168.1.10",  
  6.         "192.168.2.20",  
  7.         "192.168.3.30",  
  8.         "192.168.4.40"); 

客戶端訪問的 ip 我也模擬了一個集合:

  1. /** 
  2.      * *客戶端ip 
  3.      */ 
  4.     public static final List<String> CLIENT_IP_LIST = Arrays.asList( 
  5.         "113.88.97.173",  
  6.         "106.11.154.33",  
  7.         "207.46.13.149"
  8.         "42.156.137.120",  
  9.         "203.208.60.0",  
  10.         "119.39.47.182",  
  11.         "171.34.179.4",  
  12.         "111.175.58.52",  
  13.         "124.235.138.199"
  14.         "175.184.166.184"); 

源地址 hash 算法的思路就是對客戶端的 ip 進行 hash,然后用 hash 值與服務器的數(shù)量進行取模,得到需要訪問的服務器的 ip。只要客戶端 ip 不變,那 hash 后的值就是固定的!

實現(xiàn)如下:

  1. public static void main(String[] args) { 
  2.         for (String clientIp : CLIENT_IP_LIST) { 
  3.             int index = Math.abs(getHash(clientIp)) % PrincessConfig.SERVER_IP_LIST.size(); 
  4.             String serverIp = PrincessConfig.SERVER_IP_LIST.get(index); 
  5.             System.out.println(clientIp + "請求的服務器ip為" + serverIp); 
  6.         } 
  7.     } 

最終輸出如下:

 

這樣不管執(zhí)行多少次,相同的客戶端 ip 請求得到的服務器地址都是一樣的!

這種實現(xiàn)很簡單,但也很脆弱!因為我們服務器的數(shù)量是可能變化的,今天下線一臺機器明天增加一臺機器是很常見的!

服務器數(shù)量一旦變化,那源地址 hash 之后取模的值可能就變化了,獲取到的服務器的 ip 自然就也會發(fā)生變化!

比如我們服務器去掉一臺 192.168.4.10 的機器再看下輸出結(jié)果:

 

對比輸出結(jié)果我們就能看到,影響幾乎是全局的!那我們能不能有一種方案就算是服務器數(shù)量變化,也能減少受影響的客戶端呢?這就需要用到下面的一致性 hash 算法!

一致性 hash 算法

加權(quán)輪詢算法實現(xiàn)二中我們講到過把權(quán)重值轉(zhuǎn)化為橫坐標展示,我們這里是不是也可以用同樣的思路呢?

客戶端 ip 進行 hash 后不就是一個 int32 的數(shù)字嘛,那我們就可以把一個 int32 的數(shù)字分為幾個段,讓每個服務器負責一個段的請求!

 

下面為了直觀我們把服務器 192.168.2.10、192.168.2.20、192.168.2.30、192.168.2.40 分別用 IP1、IP2、IP3、IP4 表示,如上圖:

  • 如果客戶端 ip 進行 hash 后的值在 0~536870911 之間,那就交給 IP2 服務器處理。
  • 如果客戶端 ip 進行 hash 后的值在 536870911~1073741822 之間,那就交給 IP3 服務器處理。
  • 如果客戶端 ip 進行 hash 后的值在 1073741822~1610612733 之間,那就交給 IP4 服務器處理。
  • 如果客戶端 ip 進行 hash 后的值大于 1610612733 之間,那就交給 IP1 服務器處理。

但是專業(yè)一點的表示都會把這個橫坐標掰彎,形成一個環(huán),就叫所謂的 hash 環(huán),如下圖:

 

這樣看就更直觀了!如果有天 IP4 這臺服務器宕機,那原來需要到 IP4 的請求就會全部轉(zhuǎn)移到 IP1 服務器進行處理。

這樣對部分客戶端的請求依然會有影響,但至少影響也只是局部的,如下圖:

 

這樣就可以了嗎?我們思考兩個問題:

  • 每個服務器在 hash 環(huán)上的位置是我們?nèi)藶榈木鶆虻姆峙涞?,這樣經(jīng)常需要擴容縮容的時候會不會比較難以維護呢?
  • IP4 宕機,原本會到 IP4 的請求全部轉(zhuǎn)移到 IP1,那會不會導致 IP1 的流量不均衡?能不能有一個更均衡一點的方案讓原本到 IP4 的流量均衡的轉(zhuǎn)移到 IP1、IP2、IP3 呢?

解決問題 1 的方案就是不再人為分配結(jié)點所在的位置,而是根據(jù)服務器的 ip 計算出 hash 值,再看 hash 值落在環(huán)上的哪個位置!

這樣存在的一個問題是每個集群的服務器 ip 都會不同,因此計算后落在環(huán)上的位置可能就是不可控的。

如上面四臺服務器計算后所在的位置可能會如下圖所示:

 

很明顯,這種情況是極為不均勻的,會造成數(shù)據(jù)的傾斜!上面問題 2 的問題其實也是宕機導致的數(shù)據(jù)傾斜!

環(huán)的左上部分那么空,我們是不是可以把現(xiàn)在的 4 臺服務器再根據(jù)其他的規(guī)則在左上方生成一些結(jié)點呢?這樣是不是請求就會稍微均勻一點呢?

這就是所謂的虛擬結(jié)點!虛擬結(jié)點就是同一個服務器 ip 會根據(jù)某個規(guī)則生成多個 hashcode,這樣在環(huán)上就存在多個結(jié)點了。

如下圖所示:

 

這里只是模擬了每臺服務器有兩個虛擬結(jié)點,實際在開發(fā)中會更多!這樣就算 IP4 機器掛掉,請求也不會全部壓到某一臺服務器上去!

講了這么多,但實現(xiàn)起來也不難,下面就該上代碼了(服務器配置及請求的客戶端 ip 與源地址 hash 算法部分的一致,這里就不貼對應的代碼了,直接上算法邏輯):

  1. //虛擬結(jié)點數(shù)量100 
  2. private static final Integer VIRTUAL_NODES = 100; 
  3.  
  4. public static void main(String[] args) { 
  5.  
  6.     // 遍歷服務器ip,生成對應的虛擬結(jié)點 
  7.     TreeMap<Integer, String> nodeMap = new TreeMap<Integer, String>(); 
  8.     for (String serverIp : PrincessConfig.SERVER_IP_LIST) { 
  9.         for (int i = 0; i < VIRTUAL_NODES; i++) { 
  10.             nodeMap.put(getHash(serverIp + "VN" + i), serverIp); 
  11.         } 
  12.     } 
  13.  
  14.     for (String clientIp : CLIENT_IP_LIST) { 
  15.         //這里利用的TreeMap的特性,不清楚的可以去自己去了解一下tailMap方法的作用 
  16.         SortedMap<Integer, String> subMap = nodeMap.tailMap(getHash(clientIp)); 
  17.         Integer firstKey = null
  18.         try { 
  19.             firstKey = subMap.firstKey(); 
  20.         } catch (Exception e) { 
  21.         } 
  22.  
  23.         if (firstKey == null) { 
  24.             firstKey = nodeMap.firstKey(); 
  25.         } 
  26.         System.out.println("請求的服務器ip為" + nodeMap.get(firstKey)); 
  27.     } 

到此,幾種常用的負載均衡算法及代碼實現(xiàn)都已介紹完畢!還有不清楚可以去同性交友網(wǎng)下載示例代碼自己調(diào)試:

  1. https://github.com/sujing910206/load-balance 

作者:蘇靜

簡介:有過多年大型互聯(lián)網(wǎng)項目的開發(fā)經(jīng)驗,對高并發(fā)、分布式、以及微服務技術(shù)有深入的研究及相關(guān)實踐經(jīng)驗。經(jīng)歷過自學,熱衷于技術(shù)研究與分享!格言:始終保持虛心學習的態(tài)度!

【51CTO原創(chuàng)稿件,合作站點轉(zhuǎn)載請注明原文作者和出處為51CTO.com】

責任編輯:武曉燕 來源: 51CTO技術(shù)棧
相關(guān)推薦

2010-05-04 16:10:51

負載均衡算法

2010-04-21 11:55:34

2024-12-12 08:22:03

負載均衡算法無狀態(tài)

2010-05-05 22:51:24

2018-04-10 10:49:17

負載均衡算法服務器

2024-12-20 12:12:19

Redis負載均衡節(jié)點

2010-04-27 13:12:04

負載均衡算法

2012-11-06 16:51:29

nginx負載均衡

2023-11-28 15:32:30

負載均衡算法

2019-08-29 09:15:30

負載均衡算法備份

2010-04-26 14:52:37

2019-12-27 09:29:46

負載均衡算法哈希算法

2017-07-03 08:08:25

負載均衡分類

2009-05-01 09:33:27

應用交換負載均衡

2010-05-05 18:55:51

負載均衡算法

2010-05-10 14:11:41

負載均衡算法

2014-11-17 09:53:16

負載均衡

2023-09-06 13:58:01

負載均衡算法

2018-11-30 10:59:49

2017-02-09 16:16:24

Java負載均衡算法
點贊
收藏

51CTO技術(shù)棧公眾號