负载均衡(干货版)
admin
2024-04-26 12:03:07
0
private static Map serviceWeightMap = new HashMap();
static {serviceWeightMap.put("192.168.1.100", 1);serviceWeightMap.put("192.168.1.101", 1);		 // 权重为4serviceWeightMap.put("192.168.1.102", 4);serviceWeightMap.put("192.168.1.103", 1);serviceWeightMap.put("192.168.1.104", 1);        // 权重为3serviceWeightMap.put("192.168.1.105", 3);serviceWeightMap.put("192.168.1.106", 1);        // 权重为2serviceWeightMap.put("192.168.1.107", 2);serviceWeightMap.put("192.168.1.108", 1);serviceWeightMap.put("192.168.1.109", 1);serviceWeightMap.put("192.168.1.110", 1);
}

一、轮询法(Round Robin)

对所有的服务器节点全部按顺序来,将请求按照顺序轮流地分配到各个服务器上,所以适合用于服务器硬件条件基本都相同的情况

private static Integer pos = 0;public static String testRoundRobin() {   // 重新创建一个map,避免出现由于服务器上线和下线导致的并发问题Map serverMap = new HashMap();serverMap.putAll(serviceWeightMap);// 取得 IP 地址 listSet keySet = serverMap.keySet();ArrayList keyList = new ArrayList();keyList.addAll(keySet);String server = null;synchronized (pos) {if (pos > keySet.size()) {pos = 0;}server = keyList.get(pos);pos++;}return server;
}

由于 serviceWeightMap 中的地址列表是动态的,随时可能由机器上线、下线或者宕机,因此,为了避免可能出现的并发问题,比如数组越界,通过在方法内新建局部变量 serverMap, 先将域变量拷贝到线程本地,避免被其他线程修改。这样可能会引入新的问题,当被拷贝之后,serviceWeightMap 的修改将无法被 serverMap 感知,也就是说, 在这一轮的选择服务器中,新增服务器或者下线服务器,负载均衡算法中将无法获知。新增比较好处理,而当服务器下线或者宕机时,服务消费者将有可能访问不到不存在的地址。 因此,在服务消费者服务端需要考虑该问题,并且进行相应的容错处理,比如重新发起一次调用

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

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

二、加权轮询法(Weight Robin)

那么加权轮询算法无疑就是对各个服务器有了"高低贵贱之分",没办法,服务器的吃力水平不同,只能让那些强悍的机器优先并多处理一些请求,比较弱的机器就让它稍稍压力小一点

public class WeightRoundRobin {private static Integer pos;public static String getServer() {// 重建一个Map,避免服务器的上下线导致的并发问题Map serverMap = new HashMap();serverMap.putAll(IpMap.serverWeightMap);// 取得 Ip 地址 ListSet keySet = serverMap.keySet();Iterator iterator = keySet.iterator();List serverList = new ArrayList();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;}
}

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

三、随机法(Random)

随机算法也是一种使用场景比较多的负载均衡算法,这种算法基本思想也是很简单的,随机生成一个数字(或者随机挑一个IP地址)出来,然后挑到谁就是谁,当然, 如果随机数是等概况生成的,那时间长了,基本上跟轮询算法没有什么区别,区别最主要的还是在顺序上,随机算法没有那么严格的顺序

public class Random {public static String getServer() {// 重建一个Map,避免服务器的上下线导致的并发问题Map serverMap = new HashMap();serverMap.putAll(IpMap.serverWeightMap);// 取得 Ip 地址 ListSet keySet = serverMap.keySet();ArrayList keyList = new ArrayList();keyList.addAll(keySet);java.util.Random random = new java.util.Random();int randomPos = random.nextInt(keyList.size());return keyList.get(randomPos);}
}

四、加权随机法(Weight Random)

加权随机算法是在随机算法的基础上加了加权的条件,随机法时间长了,基本上跟一般轮询算法就没啥区别了,刚才也说到了,如果服务器的配置都差不多, 可以分配差不多的任务,但是如果服务器吃力能力差异比较大,那水平高的和水平低的服务器都给那么多任务,对于高配置的服务器来说就是有点浪费了, 对于低配置的服务器来说就有点吃不消,所以在这种配置差异性比较大的情况下,加权的工作还是必要的

public class WeightRandom {public static String getServer() {// 重建一个 Map,避免服务器的上下线导致的并发问题Map serverMap = new HashMap();serverMap.putAll(IpMap.serverWeightMap);// 取得 Ip 地址 ListSet keySet = serverMap.keySet();Iterator iterator = keySet.iterator();List serverList = new ArrayList();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)

那个服务器的连接数少,就分配给哪个服务器新的请求,合情合理,这种算法的缺点就是,当一个比较弱的服务器和一个比较彪悍的服务器,本来就是前者连接的要少, 后者要大,如果非要谁的少新请求分配给谁的话,那就是弱服务器的连接要等于强服务器的连接,无疑这样会让弱服务器吃不消,或者造成强服务器的浪费, 所以这里还可以使用加权的方法解决这样的问题------加权最小连接法

六、源地址哈希法(Hash)

源地址哈希法可以把客户端的 IP 地址拿出来,然后计算出 IP 地址的 hash 值,根据 hash 值映射到服务器上

public class Hash {public static String getServer() {// 重建一个 Map,避免服务器的上下线导致的并发问题Map serverMap = new HashMap();serverMap.putAll(IpMap.serverWeightMap);// 取得 Ip 地址 ListSet keySet = serverMap.keySet();ArrayList keyList = new ArrayList();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地址将会被哈希到同一台后端服务器,直到后端服务器列表变更。根据此特性可以在服务消费者与服务提供者之间建立有状态的 session 会话

源地址哈希算法的缺点在于:除非集群中服务器的非常稳定,基本不会上下线,否则一旦有服务器上线、下线,那么通过源地址哈希算法路由到的服务器是服务器上线、下线前路由到的服务器的概率非常低,如果是 session 则取不到 session,如果是缓存则可能引发 “雪崩”

相关内容

热门资讯

半导体存储器技术公司4DS M... ( 图片来源:《澳华财经在线》) 采访札记:当政策窗口与渠道体系开始共振——Janus Elect...
印尼央行维持利率不变,印尼盾汇... 来源:环球市场播报 印尼央行周四连续第四次会议维持利率不变,这一结果符合市场普遍预期,当前政策重心仍...
手机银行市场格局变迁:民营银行... 艾瑞咨询近日发布的《2025年中国手机银行APP监测报告》显示,中国手机银行月度总独立设备数在6.4...
开年多只FOF涨超10%!有色... 开年以来,FOF产品业绩表现迅速分化,多只产品在短短一个月内涨幅突破10%,在偏稳健定位的资产类别中...
原创 俄... 俄罗斯副外长亚历山大·格鲁什科近日向媒体直言不讳地指出,欧洲方面希望乌克兰境内的战斗“尽可能长久地持...
原创 银... 八载国有大行柜台生涯,我亲历的人情冷暖、金融百态,数不胜数。 昨日,一位熟客张姐前来办理业务,她将三...
原创 特... 特朗普这几年在国际能源场上一直玩得很主动,先是2018年5月退出伊朗核协议,紧接着分两步重启制裁。8...
手里有美元的慌了吗?人民币狂飙... 2026年一开年,人民币对美元汇率就走出了一波明显行情,短短时间内升值幅度达到1.1%,在岸、离岸汇...
原创 高... 不少人觉得预测这事儿挺神秘的,但其实靠谱的判断往往来自于数据和政策走向。把近几年公开信息和机构分析往...
中信建投证券研究所所长、首席经... 恭贺新春 时序更替,华章日新。当新年的曙光照亮前行之路,我们告别了2025年,迎来了“十五五”夯实...
【NIFD季报】美元指数走势变... 今天分享的是:【NIFD季报】美元指数走势变数加大 人民币有望温和升值——2025年年度人民币汇率分...
技术门槛降为零,Manus反击... 文 | 字母AI 就在OpenAI宣布招聘OpenClaw创始人皮特·斯坦伯格(Peter Ste...
“春捂秋冻”有道理吗 “春捂秋冻”源自先秦时期的四时养生思想,以“春夏养阳,秋冬养阴”为理论基础,强调顺应“春生夏长,秋收...
从断崖调整到价值重生,谁活下来... 《投资者网》刘亮 2025年,是白酒行业最艰难的一年。 史上最严禁酒令落地、产量连续九年下滑、六成产...
消费行业步入关键转折点,基金经... 春节期间,有券商策略团队连续7天路演,也有基金经理“下乡”实地调研。节后买什么、怎么投是他们最关注的...
原创 整... 近年来,欧洲各国的政治风云变幻,曾经在全球拥有强大影响力的欧洲大国,如今在选举中频频将领导权交给那些...
基金公司春节前后密集为债基配备... 近期,多家公募基金集中发布旗下债券型基金的基金经理增聘公告,一批擅长股票投资的基金经理被“空降”到债...
聚焦|舌尖消费引爆年味经济 春节假期,各地的传统年货与新潮餐饮交融,各色美食荟萃飘香,“舌尖上的经济”持续释放蓬勃活力,一道道新...
苏翊鸣夺金后火速官宣恋情,赛后... 北京时间2月18日晚,米兰冬奥会单板滑雪男子坡面障碍技巧决赛,苏翊鸣凭借第一滑82.41分摘得金牌,...
金价大涨!有商场1000克金条... 2月18日晚,国际贵金属价格持续走高,现货黄金再度站上5000美元/盎司,日内涨幅超2.5%。 金...