負載均衡算法--源地址哈希法(Hash)

接上一篇博文:負載均衡算法–平滑加權輪詢法(Smooth Weight Round Robin)。接下來介紹源地址哈希法。

源地址哈希法是根據請求來源的地址,通過哈希函數計算得到的一個數值,用該數值對服務器列表的大小進行取模運算,得到的結果便是客服端要訪問服務器的序號。採用源地址哈希法進行負載均衡,同一源地址的請求,當服務器列表不變時,它每次都會映射到同一臺服務器進行訪問。

算法描述

假設有 N 臺服務器 S = {S0, S1, S2, …, Sn-1},算法可以描述爲:
1、通過指定的哈希函數,計算請求來源的地址的哈希值
2、對哈希值進行求餘,底數爲 N
3、將餘數作爲索引值,從 S 中獲取對應的服務器;

假定我們現在有如下四臺服務器:

服務器地址 權重
192.168.1.1 1
192.168.1.2 2
192.168.1.3 3
192.168.1.4 4

源地址哈希法與權重沒有關係,只與源地址有關。

代碼實現

1、服務器管理類

package org.learn.loadbalance;

import java.util.Map;
import java.util.TreeMap;

/**
 * @author zhibo
 * @date 2019/5/16 16:25
 */
public class ServerManager {
    public volatile static Map<String, Integer> serverMap = new TreeMap<>();

    static {
        serverMap.put("192.168.1.1", 1);
        serverMap.put("192.168.1.2", 2);
        serverMap.put("192.168.1.3", 3);
        serverMap.put("192.168.1.4", 4);
    }
}

2、源地址哈希類

package org.learn.loadbalance;

import java.util.ArrayList;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author zhibo
 * @date 2019/5/16 16:28
 */
public class HashBalance {

    public static String getServer(String sourceIp) {
        if(sourceIp == null){
            return "";
        }
        Set<String> serverSet = ServerManager.serverMap.keySet();
        ArrayList<String> serverList = new ArrayList<>(serverSet);

        Integer index = sourceIp.hashCode() % serverList.size();
        return serverList.get(index);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            String server = getServer("ip" + new Random().nextInt(1000));
            System.out.println(server);
        }
    }
}

執行 main 方法輸出結果如下:
在這裏插入圖片描述
優點:
源地址哈希法可以保證,只要請求源地址不變,總會請求到相同的目標服務器。在早些時候進行 Web 開發時,是基於 Session 進行用戶鑑權的,用戶登錄後,會在登錄時的服務器A的 Session 中設置用戶信息,如果下一次請求被分配到服務器B上,那麼此時因 Session 中沒有用戶信息而報錯。在這種場景下一般會使用源地址哈希法進行負載均衡,保證用戶每次都可以訪問到 Session 信息。當然現在的一般不會使用 Session 進行鑑權了,大都採用 redis、memcached 等緩存服務來解決 Session 不共享的問題。

缺點:
源地址哈希法可以保證,只要請求源地址不變,總會請求到相同的目標服務器。這樣會帶來兩個問題:
1、由於用戶的活躍度不同,可能會有大量的活躍用戶被哈希到相同的服務器上,造成該服務器特別繁忙,大量的非活躍用戶被哈希到相同的服務器上,造成該服務器幾乎沒有請求,造成請求不均衡。
2、一旦某個服務器掛掉,那麼哈希到該服務器的所有源請求都會失敗,直到服務恢復或者服務器列表中去掉該服務器。

文章內容僅代表個人觀點,如有不正之處,歡迎批評指正,謝謝大家。

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