负载均衡算法--源地址哈希法(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 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 serverSet = ServerManager.serverMap.keySet();
        ArrayList 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 方法输出结果如下:
负载均衡算法--源地址哈希法(Hash)_第1张图片
优点:
源地址哈希法可以保证,只要请求源地址不变,总会请求到相同的目标服务器。在早些时候进行 Web 开发时,是基于 Session 进行用户鉴权的,用户登录后,会在登录时的服务器A的 Session 中设置用户信息,如果下一次请求被分配到服务器B上,那么此时因 Session 中没有用户信息而报错。在这种场景下一般会使用源地址哈希法进行负载均衡,保证用户每次都可以访问到 Session 信息。当然现在的一般不会使用 Session 进行鉴权了,大都采用 redis、memcached 等缓存服务来解决 Session 不共享的问题。

缺点:
源地址哈希法可以保证,只要请求源地址不变,总会请求到相同的目标服务器。这样会带来两个问题:
1、由于用户的活跃度不同,可能会有大量的活跃用户被哈希到相同的服务器上,造成该服务器特别繁忙,大量的非活跃用户被哈希到相同的服务器上,造成该服务器几乎没有请求,造成请求不均衡。
2、一旦某个服务器挂掉,那么哈希到该服务器的所有源请求都会失败,直到服务恢复或者服务器列表中去掉该服务器。

文章内容仅代表个人观点,如有不正之处,欢迎批评指正,谢谢大家。

你可能感兴趣的:(负载均衡,Java编程,数据结构与算法)