阅读更多

6顶
1踩

编程语言

首先给大家介绍下什么是负载均衡(来自百科)
负载均衡 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和 服务器的带宽、增加 吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。
负载均衡,英文名称为Load Balance,其意思就是分摊到多个操作单元上进行执行,例如Web 服务器、 FTP服务器、 企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。

本文讲述的是"将外部发送来的请求均匀分配到对称结构中的某一台服务器上"的各种算法,并以Java代码演示每种算法的具体实现,OK,下面进入正题,在进入正题前,先写一个类来模拟Ip列表:
import java.util.HashMap;

/**
 * @author ashang.peng@aliyun.com
 * @date 二月 07, 2017
 */

public class IpMap   {
    // 待路由的Ip列表,Key代表Ip,Value代表该Ip的权重
    public static HashMap<String, Integer> serverWeightMap =
            new HashMap<String, Integer>();

    static
    {
        serverWeightMap.put("192.168.1.100", 1);
        serverWeightMap.put("192.168.1.101", 1);
        // 权重为4
        serverWeightMap.put("192.168.1.102", 4);
        serverWeightMap.put("192.168.1.103", 1);
        serverWeightMap.put("192.168.1.104", 1);
        // 权重为3
        serverWeightMap.put("192.168.1.105", 3);
        serverWeightMap.put("192.168.1.106", 1);
        // 权重为2
        serverWeightMap.put("192.168.1.107", 2);
        serverWeightMap.put("192.168.1.108", 1);
        serverWeightMap.put("192.168.1.109", 1);
        serverWeightMap.put("192.168.1.110", 1);
    }
}


轮询(Round Robin)法
轮询调度算法的原理是每一次把来自用户的请求轮流分配给内部中的服务器,从1开始,直到N(内部服务器个数),然后重新开始循环。算法的优点是其简洁性,它无需记录当前所有连接的状态,所以它是一种无状态调度。

其代码实现大致如下:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author ashang.peng@aliyun.com
 * @date 二月 07, 2017
 */

class RoundRobin   {
    private static Integer pos = 0;

    public static String getServer()
    {
        // 重建一个Map,避免服务器的上下线导致的并发问题
        Map<String, Integer> serverMap =
                new HashMap<String, Integer>();
        serverMap.putAll(IpMap.serverWeightMap);

        // 取得Ip地址List
        Set<String> keySet = serverMap.keySet();
        ArrayList<String> keyList = new ArrayList<String>();
        keyList.addAll(keySet);

        String server = null;
        synchronized (pos)
        {
            if (pos > keySet.size())
                pos = 0;
            server = keyList.get(pos);
            pos ++;
        }

        return server;
    }
}

由于serverWeightMap中的地址列表是动态的,随时可能有机器上线、下线或者宕机,因此为了避免可能出现的并发问题,方法内部要新建局部变量serverMap,现将serverMap中的内容复制到线程本地,以避免被多个线程修改。这样可能会引入新的问题,复制以后serverWeightMap的修改无法反映给serverMap,也就是说这一轮选择服务器的过程中,新增服务器或者下线服务器,负载均衡算法将无法获知。新增无所谓,如果有服务器下线或者宕机,那么可能会访问到不存在的地址。因此,服务调用端需要有相应的容错处理,比如重新发起一次server选择并调用。

对于当前轮询的位置变量pos,为了保证服务器选择的顺序性,需要在操作时对其加锁,使得同一时刻只能有一个线程可以修改pos的值,否则当pos变量被并发修改,则无法保证服务器选择的顺序性,甚至有可能导致keyList数组越界。

轮询法的优点在于:试图做到请求转移的绝对均衡。

轮询法的缺点在于:为了做到请求转移的绝对均衡,必须付出相当大的代价,因为为了保证pos变量修改的互斥性,需要引入重量级的悲观锁synchronized,这将会导致该段轮询代码的并发吞吐量发生明显的下降。

随机(Random)法
通过系统的随机算法,根据后端服务器的列表大小值来随机选取其中的一台服务器进行访问。由概率统计理论可以得知,随着客户端调用服务端的次数增多,

其实际效果越来越接近于平均分配调用量到后端的每一台服务器,也就是轮询的结果。

随机法的代码实现大致如下:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author ashang.peng@aliyun.com
 * @date 二月 07, 2017
 */

 class Random   {
    public static String getServer()
    {
        // 重建一个Map,避免服务器的上下线导致的并发问题   
        Map<String, Integer> serverMap =
                new HashMap<String, Integer>();
        serverMap.putAll(IpMap.serverWeightMap);

        // 取得Ip地址List   
        Set<String> keySet = serverMap.keySet();
        ArrayList<String> keyList = new ArrayList<String>();
        keyList.addAll(keySet);

        java.util.Random random = new java.util.Random();
        int randomPos = random.nextInt(keyList.size());

        return keyList.get(randomPos);
    }
}


整体代码思路和轮询法一致,先重建serverMap,再获取到server列表。在选取server的时候,通过Random的nextInt方法取0~keyList.size()区间的一个随机值,从而从服务器列表中随机获取到一台服务器地址进行返回。基于概率统计的理论,吞吐量越大,随机算法的效果越接近于轮询算法的效果。

源地址哈希(Hash)法
源地址哈希的思想是根据获取客户端的IP地址,通过哈希函数计算得到的一个数值,用该数值对服务器列表的大小进行取模运算,得到的结果便是客服端要访问服务器的序号。采用源地址哈希法进行负载均衡,同一IP地址的客户端,当后端服务器列表不变时,它每次都会映射到同一台后端服务器进行访问。

源地址哈希算法的代码实现大致如下:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author ashang.peng@aliyun.com
 * @date 二月 07, 2017
 */

 class Hash      {
    public static String getServer()
    {
        // 重建一个Map,避免服务器的上下线导致的并发问题
        Map<String, Integer> serverMap =
                new HashMap<String, Integer>();
        serverMap.putAll(IpMap.serverWeightMap);

        // 取得Ip地址List
        Set<String> keySet = serverMap.keySet();
        ArrayList<String> keyList = new ArrayList<String>();
        keyList.addAll(keySet);

        // 在Web应用中可通过HttpServlet的getRemoteIp方法获取
        String remoteIp = "127.0.0.1";
        int hashCode = remoteIp.hashCode();
        int serverListSize = keyList.size();
        int serverPos = hashCode % serverListSize;

        return keyList.get(serverPos);
    }
}

前两部分和轮询法、随机法一样就不说了,差别在于路由选择部分。通过客户端的ip也就是remoteIp,取得它的Hash值,对服务器列表的大小取模,结果便是选用的服务器在服务器列表中的索引值。

源地址哈希法的优点在于:保证了相同客户端IP地址将会被哈希到同一台后端服务器,直到后端服务器列表变更。根据此特性可以在服务消费者与服务提供者之间建立有状态的session会话。

源地址哈希算法的缺点在于:除非集群中服务器的非常稳定,基本不会上下线,否则一旦有服务器上线、下线,那么通过源地址哈希算法路由到的服务器是服务器上线、下线前路由到的服务器的概率非常低,如果是session则取不到session,如果是缓存则可能引发"雪崩"。如果这么解释不适合明白,可以看我之前的一篇文章MemCache超详细解读,一致性Hash算法部分。

加权轮询(Weight Round Robin)法
不同的后端服务器可能机器的配置和当前系统的负载并不相同,因此它们的抗压能力也不相同。给配置高、负载低的机器配置更高的权重,让其处理更多的请;而配置低、负载高的机器,给其分配较低的权重,降低其系统负载,加权轮询能很好地处理这一问题,并将请求顺序且按照权重分配到后端。加权轮询法的代码实现大致如下:
import java.util.*;

/**
 * @author ashang.peng@aliyun.com
 * @date 二月 07, 2017
 */
class WeightRoundRobin   {
    private static Integer pos;

    public static String getServer()
    {
        // 重建一个Map,避免服务器的上下线导致的并发问题
        Map<String, Integer> serverMap =
                new HashMap<String, Integer>();
        serverMap.putAll(IpMap.serverWeightMap);

        // 取得Ip地址List
        Set<String> keySet = serverMap.keySet();
        Iterator<String> iterator = keySet.iterator();

        List<String> serverList = new ArrayList<String>();
        while (iterator.hasNext())
        {
            String server = iterator.next();
            int weight = serverMap.get(server);
            for (int i = 0; i < weight; i++)
                serverList.add(server);
        }

        String server = null;
        synchronized (pos)
        {
            if (pos > keySet.size())
                pos = 0;
            server = serverList.get(pos);
            pos ++;
        }

        return server;
    }
}

与轮询法类似,只是在获取服务器地址之前增加了一段权重计算的代码,根据权重的大小,将地址重复地增加到服务器地址列表中,权重越大,该服务器每轮所获得的请求数量越多。

加权随机(Weight Random)法
与加权轮询法一样,加权随机法也根据后端机器的配置,系统的负载分配不同的权重。不同的是,它是按照权重随机请求后端服务器,而非顺序。
import java.util.*;

/**
 * @author ashang.peng@aliyun.com
 * @date 二月 07, 2017
 */

 class WeightRandom   {
    public static String getServer()
    {
        // 重建一个Map,避免服务器的上下线导致的并发问题
        Map<String, Integer> serverMap =
                new HashMap<String, Integer>();
        serverMap.putAll(IpMap.serverWeightMap);

        // 取得Ip地址List
        Set<String> keySet = serverMap.keySet();
        Iterator<String> iterator = keySet.iterator();

        List<String> serverList = new ArrayList<String>();
        while (iterator.hasNext())
        {
            String server = iterator.next();
            int weight = serverMap.get(server);
            for (int i = 0; i < weight; i++)
                serverList.add(server);
        }

        java.util.Random random = new java.util.Random();
        int randomPos = random.nextInt(serverList.size());

        return serverList.get(randomPos);
    }
}

这段代码相当于是随机法和加权轮询法的结合,比较好理解,就不解释了。

最小连接数(Least Connections)法
最小连接数算法比较灵活和智能,由于后端服务器的配置不尽相同,对于请求的处理有快有慢,它是根据后端服务器当前的连接情况,动态地选取其中当前

积压连接数最少的一台服务器来处理当前的请求,尽可能地提高后端服务的利用效率,将负责合理地分流到每一台服务器。

前面几种方法费尽心思来实现服务消费者请求次数分配的均衡,当然这么做是没错的,可以为后端的多台服务器平均分配工作量,最大程度地提高服务器的利用率,但是实际情况是否真的如此?实际情况中,请求次数的均衡真的能代表负载的均衡吗?这是一个值得思考的问题。

上面的问题,再换一个角度来说就是:以后端服务器的视角来观察系统的负载,而非请求发起方来观察。最小连接数法便属于此类。

最小连接数算法比较灵活和智能,由于后端服务器的配置不尽相同,对于请求的处理有快有慢,它正是根据后端服务器当前的连接情况,动态地选取其中当前积压连接数最少的一台服务器来处理当前请求,尽可能地提高后端服务器的利用效率,将负载合理地分流到每一台机器。由于最小连接数设计服务器连接数的汇总和感知,设计与实现较为繁琐,此处就不说它的实现了。
  • 大小: 129.7 KB
来自: duzhi
6
1
评论 共 6 条 请登录后发表评论
6 楼 jeffsc 2017-02-13 11:54
加权轮询算法
这行代码pos > keySet.size()
是不是应该改为
pos > serverList.size()
5 楼 田梦桦 2017-02-13 09:49
基本的算法实现  优缺点说的很明确   这个必须给赞    
4 楼 fjjiaboming 2017-02-10 17:50
性能真差:
与轮询法类似,只是在获取服务器地址之前增加了一段权重计算的代码,根据权重的大小,将地址重复地增加到服务器地址列表中,权重越大,该服务器每轮所获得的请求数量越多。
 
3 楼 fjjiaboming 2017-02-10 17:50
性能真差:
与轮询法类似,只是在获取服务器地址之前增加了一段权重计算的代码,根据权重的大小,将地址重复地增加到服务器地址列表中,权重越大,该服务器每轮所获得的请求数量越多。
 
2 楼 woshiyexinjie 2017-02-09 17:57
讲的挺明白易懂 
1 楼 jiong9 2017-02-08 19:56
学习了,负载均衡觉得好高深。。。记得之前csdn就是负载均衡做错了,导致好多地区上不去

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • java负载均衡原理_多种负载均衡算法及其 Java 代码实现

    首先给我们介绍下什么是负载均衡负载均衡 树立在现有网络结构之上,它供给了一种廉价有用通明的办法扩展 网络设备和 效劳器的带宽、添加 吞吐量、加强网络数据处理才能、进步网络的灵敏性...多种负载均衡算法及其Ja...

  • Python零基础30天速通(小白定制版)(完结)

    宣导片:开启Python进阶之路 30动漫番剧播放量影响因素分析1综合案例 29小红书卖货实力与用户分析1综合案例 28星巴克门店探索|Matplotlib实战 27詹姆斯哈登的制胜宝典1 Panads的使用 26一晚5万的酒店| Numpy的使用 25揭开数据分析的面纱1数据分析"三剑客"概述 24虎牙直播数据告诉你谁最火1案例篇 23我的音乐我做主1数据保存之csv和excel 22电竟| BeautifulSoup解析HTML 21对李焕英的评价1HTML基础 20我的美食我做主1爬虫介绍、requests请 19看我四十二变1内容提取和格式转换 18我的版权我做主1PDF就是这么帅 17婚礼策划师离不开你|亲爱的PPT 16运营部的烦恼1战胜Excel 15Up主的创作之路1 Python与word初次 14你的offer之选|邮件发送 13我的存在只为悦你1 Pillow图片处理 12你喜欢的电竟赛事大全1 Python的文件操作 11哈利波特的魔法棒|模块 10龙珠之赛亚人1面向对象基础 09大吉大利今晚吃鸡1特种兵的战场(项目案

  • 20240519基本完整

    20240519基本完整

  • MATLAB仿真项目-大数据源码-疲劳检测识别,可应用于疲劳驾驶监测,专注度检测等(高分期末大作业).rar

    本项目提供了一个基于MATLAB的疲劳检测识别仿真系统,旨在帮助计算机相关专业的在校学生、老师和企业员工更好地学习和实践大数据与人工智能技术。该项目可应用于疲劳驾驶监测、专注度检测等领域,具有较高的实用价值。 项目源码已经过运行测试,确保OK,可作为课程设计、毕业设计的优质资源。此外,我们还为您提供了一些网络相关资源,以便您在学习过程中进行参考。这些资源将帮助您更好地理解项目的原理和应用。 本项目的源码适用于初学者,即使是编程基础较弱的同学也能快速上手。同时,源码结构清晰,易于理解和修改。您可以在这个基础上进行二次开发,实现更多有趣的功能。 请放心下载使用,我们为您提供了详细的文档说明,以便您更好地了解和使用该项目。希望这个项目能为您提供实质性的帮助,祝您在学习和工作中取得更好的成绩!

  • 利用协同过滤算法,基于用户历史订单数据,对店铺的用户和商品进行推荐.zip

    协同过滤算法(Collaborative Filtering)是一种经典的推荐算法,其基本原理是“协同大家的反馈、评价和意见,一起对海量的信息进行过滤,从中筛选出用户可能感兴趣的信息”。它主要依赖于用户和物品之间的行为关系进行推荐。 协同过滤算法主要分为两类: 基于物品的协同过滤算法:给用户推荐与他之前喜欢的物品相似的物品。 基于用户的协同过滤算法:给用户推荐与他兴趣相似的用户喜欢的物品。 协同过滤算法的优点包括: 无需事先对商品或用户进行分类或标注,适用于各种类型的数据。 算法简单易懂,容易实现和部署。 推荐结果准确性较高,能够为用户提供个性化的推荐服务。 然而,协同过滤算法也存在一些缺点: 对数据量和数据质量要求较高,需要大量的历史数据和较高的数据质量。 容易受到“冷启动”问题的影响,即对新用户或新商品的推荐效果较差。 存在“同质化”问题,即推荐结果容易出现重复或相似的情况。 协同过滤算法在多个场景中有广泛的应用,如电商推荐系统、社交网络推荐和视频推荐系统等。在这些场景中,协同过滤算法可以根据用户的历史行为数据,推荐与用户兴趣相似的商品、用户或内容,从而提高用户的购买转化率、活跃度和社交体验。 未来,协同过滤算法的发展方向可能是结合其他推荐算法形成混合推荐系统,以充分发挥各算法的优势。

  • 用C#实现人工智能中的八数码问题,有界面效果,可以得出结果,也可以逐步求解.zip

    用C#实现人工智能中的八数码问题,有界面效果,可以得出结果,也可以逐步求解.zip

  • Matlab 太阳能电池 simulink 模型太阳能电池模型连接到巴克 converter.by

    Matlab 太阳能电池 simulink 模型太阳能电池模型连接到巴克 converter.by 不同占空比和 PS 转炉值,我们可以改变输出 voltage.buck 转换器调节来自太阳能电池的电压,因而顺利和调节直流电压在负载的忧伤。通过将许多细胞我们可以使太阳能机舱和增加输出电压电流 (串联或并联).zip

  • npy 文件的基本结构和内容

    npy 文件的基本结构和内容

  • Learning Python 5th Edition

    Learning Python 5th Edition

  • Learning Docker

    Learning Docker

  • SwiftUI-加载动画 圆点循环缩放动画

    SwiftUI-加载动画 圆点循环缩放动画

  • 一种用于非线性模型预测控制的并行优化工具包(NMPC)

    介绍了一种专为非线性模型预测控制(NMPC)设计的并行优化工具包。内容涉及该工具包的功能特点、使用方法以及在解决非线性控制问题中的应用实例。通过对比分析,突出了并行优化在提高NMPC计算效率和实时性方面的重要作用。适合控制工程师、算法研究员和对高性能计算感兴趣的专业人士。使用场景包括复杂系统控制、实时仿真和工业自动化。目标是推广这一工具包的使用,助力非线性控制系统的研究与开发。 关键词标签: 非线性模型预测控制 NMPC 并行优化 工具包 实时控制

  • matlab矩阵位移法实现有限元求解.zip

    matlab矩阵位移法实现有限元求解.zip

  • Matlab 交互式多模型目标跟踪IMM.zip

    Matlab 交互式多模型目标跟踪IMM.zip

  • 520节日李珣的爱心代码

    内容概要:本项目是李珣创作的“爱心代码”,旨在通过编程表达浪漫与情感。该项目使用JavaScript编写,生成一个动态的爱心图案,并可以附加个性化的文字祝福。代码逻辑简单清晰,适合在网页上展示和分享。源码提供了完整的代码文件,部署文档详细介绍了代码的使用方法和展示步骤,讲解内容涵盖了代码的实现原理、技术选型理由、设计思路以及使用方法。 适合人群:对JavaScript有基础了解,并希望通过编程表达情感的开发者和编程爱好者。 能学到什么: 1. 掌握JavaScript绘图和动画的实现方法。 2. 学习如何通过代码生成动态图案。 3. 了解简单的前端开发和部署流程。 4. 掌握个性化定制代码的技巧。 阅读建议:本资源旨在帮助学习者通过实践项目掌握JavaScript的绘图和动画实现方法,并了解如何通过编程表达情感。建议在学习过程中结合部署文档进行实践,并深入理解讲解内容中的技术原理和设计思路。同时,鼓励学习者根据实际需求对代码进行拓展和优化,以提升自己的技术水平和创造力。

  • python源码毕业设计基于深度学习的水果识别系统源码+文档说明+数据集+模型(期末大作业项目).rar

    本源码提供了一个基于深度学习的水果识别系统,涵盖了Python编程、深度学习、图像识别等多个领域的技术。项目利用神经网络模型对水果图像进行分类,实现了高效的水果识别功能。适合计算机专业的学生、老师和从业人员学习和参考,尤其是对深度学习图像识别感兴趣的朋友。 核心功能包括: 1. 数据集:包含大量水果图片,用于训练和测试模型。 2. 模型训练:采用卷积神经网络(CNN)进行训练,提升模型精度。 3. 图像识别:加载预训练模型,对新图像预测类别。 4. 测试验证:确保模型准确性和实用性。 代码可用于毕业设计、课程设计等,快速构建原型,基于此优化和扩展。 资源丰富,包含详细文档,讲解代码结构和算法;提供数据集和预训练模型,方便测试;代码清晰易懂,结构完整,便于理解深度学习图像识别。 请放心下载,这是经过测试的高质量资源,助你取得课程设计高分!

  • Java项目毕业设计-航空订票系统(前台订票+后台票务管理)基于SSM开发+数据库(详细源码)-期末大作业.rar

    本项目为Java项目毕业设计-航空订票系统,基于SSM框架开发,结合前台订票与后台票务管理功能,满足现代航空票务需求。系统采用三层架构,包括表现层、业务逻辑层和数据访问层,确保高效稳定运行。数据库设计考虑数据完整性和安全性,采用MySQL数据库存储关键数据。 经过运行测试,系统性能良好,满足设计要求。界面简洁直观,用户友好;后台管理功能强大,方便管理员管理。系统安全性高,有效防止SQL注入、跨站脚本等攻击。 本资源适合计算机相关专业学生和从业者下载学习。对初学者,可快速掌握SSM框架和航空订票系统开发流程;对有一定基础者,可作为参考,拓宽思路,提升技能。此外,也适用于毕业设计、课程设计、项目立项等场景,展现项目基本框架和功能。 请放心下载使用,相信能助您顺利完成学习和项目任务。期待在您的努力下,系统不断完善,功能更加丰富,为航空事业发展贡献力量。

  • web期末大作业-基于html+css+js实现的模仿华为商城静态网页源码+项目说明(附静态网页效果链接).rar

    本学期Web期末大作业,我们为您呈现一个精心制作的静态网页源码项目——基于HTML+CSS+JS实现的仿华为商城。经过严格的运行测试,我们确保该项目在各大主流浏览器中均能完美呈现,无兼容性问题。 这个项目不仅是一个简单的网页复刻,更是一次对前端技术的全面实践。我们采用了HTML5标准编写页面结构,利用CSS3实现丰富的样式与动画效果,同时运用JavaScript进行交互逻辑的编写,使得整个页面动态而生动。 我们深知每位同学的需求不同,因此这个项目的源码设计得非常灵活,易于修改和扩展。无论您是想学习前端技术的基础知识,还是想借鉴实际项目经验,亦或是作为课程设计的素材,这个项目都能满足您的需求。 请放心下载使用,我们承诺提供完善的售后服务和技术支持。遇到任何问题,欢迎随时与我们联系。相信通过这个项目,您一定能获得宝贵的实践经验,为未来的学习和职业生涯打下坚实的基础。

Global site tag (gtag.js) - Google Analytics