阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

几种负载均衡的算法原理及代码实现

16次阅读
没有评论

共计 3830 个字符,预计需要花费 10 分钟才能阅读完成。

导读 轮询算法:将接收到的请求依次转发到后端服务器上,它均衡对待(一视同仁)所有服务器,而不关心当前服务器实际连接数及当前系统负载。

轮询算法:将接收到的请求依次转发到后端服务器上,它均衡对待(一视同仁)所有服务器,而不关心当前服务器实际连接数及当前系统负载。这里实现一个简单的轮询系统:

public class RoundRobin {
static Integer position = 0;
public static List initServerList() {List servers = new ArrayList();
servers.add("192.168.10.00");
servers.add("192.168.10.01");
servers.add("192.168.10.02");
servers.add("192.168.10.03");
servers.add("192.168.10.04");
servers.add("192.168.10.05");
servers.add("192.168.10.06");
return servers;
}
public static String getServerUrl() {
// 新建立一个 List 赋值,避免服务器上下线导致的并发问题
List serverList = new ArrayList();
serverList.addAll(initServerList());
String server = null;
synchronized (position){if(position >= serverList.size()) {position = 0;}
server = serverList.get(position);
position ++;
}
return server;
}
public static void main(String[] args) {while (true){System.out.println(getServerUrl());
}
}
}

在实际生产环境中,我们还得考虑诸多因素,比如:
几种负载均衡的算法原理及代码实现
新增服务器 ip 如何处理?这个比较简单,直接添加到 initServerList() 即可。

出现服务宕机怎么办?比如 192.168.10.01 所在服务器挂掉了,请求被转发给它,就会报错。这时,需要服务的消费者考虑容错处理,在这种情况下,比如再发一次请求,那就会被转发到 192.168.10.02 机器上,正常。该方法最大缺点是引用了悲观锁 synchronized,影响系统的并发性能。

每台机器的配置不一样,有单核 CPU,2G 内存,有 8 核 CPU,32G 内存。这种情形下,使用上述轮询,那就不公平了,对弱配置机器,压力很大。这个,我们可以引入

加权轮询:每台服务器,给一个权重值,权值高的,多分配点儿请求,权值少的,少分配点儿请求,。实现思路也很简单,根据权值,重新构建服务列表,然后再轮询。上个图示:

如下是代码实现:

public class WeightRoundRobin {
static Integer position = 0;
public static Map initServicesMap() {Map servicesMap = new HashMap();
servicesMap.put("192.168.10.00", 1);
servicesMap.put("192.168.10.02", 3);
servicesMap.put("192.168.10.03", 3);
servicesMap.put("192.168.10.04", 5);
servicesMap.put("192.168.10.05", 5);
servicesMap.put("192.168.10.06", 5);
return servicesMap;
}
public static String getServerUrl() {
// 新建立一个 List 赋值,避免服务器上下线导致的并发问题
Map initMap = new HashMap();
initMap = initServicesMap();
Set servicesSet = new HashSet();
servicesSet.addAll(initMap.keySet());
Iterator servicesIterator = servicesSet.iterator();
List servicesList = new ArrayList();
while (servicesIterator.hasNext()) {String server = servicesIterator.next();
Integer weight = initMap.get(server);
if(weight > 0) {for(int i=0; i= servicesList.size()) {position = 0;}
server = servicesList.get(position);
position ++;
}
return server;
}
public static void main(String[] args) {while (true){System.out.println(getServerUrl());
}
}
}
随机算法:

顾名思义:现有 N 个服务器 ip 地址,请求来了后,随机转发到某个服务器上。从概率的角度来说,随着请求数的增多,最终每台服务器分配到的请求,近似于均等。这就比轮询算法少了个悲观锁,并发性能上,有了极大的提升。

实现也很简单:

如下:

public class RandomDemo {public static List initServerList() {List servers = new ArrayList();
servers.add("192.168.10.00");
servers.add("192.168.10.01");
servers.add("192.168.10.02");
servers.add("192.168.10.03");
servers.add("192.168.10.04");
servers.add("192.168.10.05");
servers.add("192.168.10.06");
return servers;
}
public static String getServerUrl() {
// 新建立一个 List 赋值,避免服务器上下线导致的并发问题
List serverList = new ArrayList();
serverList.addAll(initServerList());
int position = new Random().nextInt(serverList.size());
return serverList.get(position);
}
public static void main(String[] args) {while (true) {System.out.println(getServerUrl());
}
}
}

但他也有与简单轮询算法一样的问题:

对于不同性能的服务器,依旧一视同仁,那其实是不公平的。低配置,应该少分点请求嘛。

这就有了

加权随机算法,其实现思想同 加权轮询算法一样,给不同配置的服务器,配置不同的权重值。代码实现也同加权轮询思路一样,构建出符合权重值的服务集合后,再进行随机选取,这里就不写了,留给大家自己去写吧。

源地址哈希(hashCode)法:根据客户端的请求 ip,通过哈希计算,得到一个数值,随后与服务器列表个数,进行取模计算,得到该请求 访问服务器列表的序号。该方法,有个好处是,当服务器列表不变时,某个客户端,会始终访问某一个固定的服务器,这样就可以构建一个客户端 – 服务器之间,有状态的 session。

代码实现:

public class HashDemo {public static List initServerList() {List servers = new ArrayList();
servers.add("192.168.10.00");
servers.add("192.168.10.01");
servers.add("192.168.10.02");
servers.add("192.168.10.03");
servers.add("192.168.10.04");
servers.add("192.168.10.05");
servers.add("192.168.10.06");
return servers;
}
public static String getServerUrl() {
// 新建立一个 List 赋值,避免服务器上下线导致的并发问题
List serverList = new ArrayList();
serverList.addAll(initServerList());
int requestIpHashCode = "192.168.10.06.109".hashCode();
int position = requestIpHashCode % serverList.size();
return serverList.get(position);
}
public static void main(String[] args) {while (true) {System.out.println(getServerUrl());
}
}
}

阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配

腾讯云新客低至 82 元 / 年,老客户 99 元 / 年

代金券:在阿里云专用满减优惠券

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2025-02-07发表,共计3830字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中