Dubbo学习笔记第七章: Dubbo的负载均衡原理解析

负载均衡介绍

 

负载均衡,英文名称为Load Balance,指由多台服务器以对称的方式组成一个服务器集合,每台服务器都具有等价的地位,都可以单独对外提供服务而无须其他服务器的辅助。

通过某种负载分担技术,将外部发送来的请求均匀分配到对称结构中的某一台服务器上,而接收到请求的服务器独立地回应客户的请求。

负载均衡能够平均分配客户请求到服务器阵列,借此提供快速获取重要数据,解决大量并发访问服务问题,这种集群技术可以用最少的投资获得接近于大型主机的性能。

 

负载均衡方式

 

负载均衡分为软件负载均衡和硬件负载均衡

建议没有相关软件使用经验的同学不要太纠结他们的不同之处,可继续往下看。

 

软件负载均衡

 

常见的负载均衡软件有Nginx、LVS、HAProxy。

关于这几个软件的特点比较不是本文重点,感兴趣同学可以参见博客:

 

  • (总结)Nginx/LVS/HAProxy负载均衡软件的优缺点详解:http://www.ha97.com/5646.html
  • 三大主流软件负载均衡器对比(LVS 、 Nginx 、Haproxy):http://www.21yunwei.com/archives/5824

 

硬件负载均衡

 

常见的负载均衡硬件有Array、F5。

 

负载均衡算法

 

常见的负载均衡算法有:随机算法、加权轮询、一致性hash、最小活跃数算法。

千万别以为这几个算法看上去都特别简单,但其实真正在生产上用到时会远比你想的复杂

 

算法前提条件

 

定义一个服务器列表,每个负载均衡的算法会从中挑出一个服务器作为算法的结果。

 

public class ServerIps {
    private static final List LIST = Arrays.asList(
            "192.168.0.1",
            "192.168.0.2",
            "192.168.0.3",
            "192.168.0.4",
            "192.168.0.5",
            "192.168.0.6",
            "192.168.0.7",
            "192.168.0.8",
            "192.168.0.9",
            "192.168.0.10"
    );
}

 

随机算法-RandomLoadBalance

 

先来个最简单的实现。

 

public class Random {
    public static String getServer() {
        // 生成一个随机数作为list的下标值
        java.util.Random random = new java.util.Random();
        int randomPos = random.nextInt(ServerIps.LIST.size());
        return ServerIps.LIST.get(randomPos);
    }
    public static void main(String[] args) {
        // 连续调用10次
        for (int i=0; i<10; i++) {
            System.out.println(getServer());
        }
    }
}

 

运行结果:
192.168.0.3
192.168.0.4
192.168.0.7
192.168.0.1
192.168.0.2
192.168.0.7
192.168.0.3
192.168.0.9
192.168.0.1
192.168.0.1

 

当调用次数比较少时,Random 产生的随机数可能会比较集中,此时多数请求会落到同一台服务器上,只有在经过多次请求后,才能使调用请求进行“均匀”分配。调用量少这一点并没有什么关系,负载均衡机制不正是为了应对请求量多的情况吗,所以随机算法也是用得比较多的一种算法。

 

但是,上面的随机算法适用于每天机器的性能差不多的时候,实际上,生产中可能某些机器的性能更高一点,它可以处理更多的请求,所以,我们可以对每台服务器设置一个权重。

在ServerIps类中增加服务器权重对应关系MAP,权重之和为50:

 

public static final Map WEIGHT_LIST = new HashMap();
    static {
        // 权重之和为50
        WEIGHT_LIST.put("192.168.0.1", 1);
        WEIGHT_LIST.put("192.168.0.2", 8);
        WEIGHT_LIST.put("192.168.0.3", 3);
        WEIGHT_LIST.put("192.168.0.4", 6);
        WEIGHT_LIST.put("192.168.0.5", 5);
        WEIGHT_LIST.put("192.168.0.6", 5);
        WEIGHT_LIST.put("192.168.0.7", 4);
        WEIGHT_LIST.put("192.168.0.8", 7);
        WEIGHT_LIST.put("192.168.0.9", 2);
        WEIGHT_LIST.put("192.168.0.10", 9);
    }

 

那么现在的随机算法应该要改成权重随机算法,当调用量比较多的时候,服务器使用的分布应该近似对应权重的分布。

 

权重随机算法

 

简单的实现思路是,把每个服务器按它所对应的服务器进行复制,具体看代码更加容易理解

 

public class WeightRandom {
    public static String getServer() {
        // 生成一个随机数作为list的下标值
        List ips = new ArrayList();
        for (String ip : ServerIps.WEIGHT_LIST.keySet()) {
            Integer weight = ServerIps.WEIGHT_LIST.get(ip);
            // 按权重进行复制
            for (int i=0; i 
  

 

运行结果:
192.168.0.8
192.168.0.2
192.168.0.7
192.168.0.10
192.168.0.8
192.168.0.8
192.168.0.4
192.168.0.7
192.168.0.6
192.168.0.8

 

这种实现方法在遇到权重之和特别大的时候就会比较消耗内存,因为需要对ip地址进行复制,权重之和越大那么上文中的ips就需要越多的内存,下面介绍另外一种实现思路。

假设我们有一组服务器 servers = [A, B, C],他们对应的权重为 weights = [5, 3, 2],权重总和为10。现在把这些权重值平铺在一维坐标值上,[0, 5) 区间属于服务器 A,[5, 8) 区

你可能感兴趣的:(dubbo学习笔记,java)