学习
实践
活动
工具
TVP
写文章

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

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

public classRoundRobin{

staticIntegerposition=;

public staticListinitServerList() {

List servers =newArrayList();

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");

returnservers;

}

public staticStringgetServerUrl() {

//新建立一个List赋值,避免服务器上下线导致的并发问题

List serverList =newArrayList();

serverList.addAll(initServerList());

Stringserver =null;

synchronized(position){

if(position>= serverList.size()) {

position=;

}

server = serverList.get(position);

position++;

}

returnserver;

}

public static voidmain(String[]args) {

while(true){

}

}

}

在实际生产环境中,我们还得考虑诸多因素,比如:

新增服务器ip如何处理? 这个比较简单,直接添加到initServerList()即可。

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

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

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

如下是代码实现:

public classWeightRoundRobin{

staticIntegerposition=;

public staticMapinitServicesMap() {

Map servicesMap =newHashMap();

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);

returnservicesMap;

}

public staticStringgetServerUrl() {

//新建立一个List赋值,避免服务器上下线导致的并发问题

Map initMap =newHashMap();

initMap =initServicesMap();

Set servicesSet =newHashSet();

servicesSet.addAll(initMap.keySet());

Iterator servicesIterator = servicesSet.iterator();

List servicesList =newArrayList();

while(servicesIterator.hasNext()) {

Stringserver = servicesIterator.next();

Integerweight = initMap.get(server);

if(weight >) {

for(inti=; i

servicesList.add(server);

}

}

}

Stringserver =null;

synchronized(position){

if(position>= servicesList.size()) {

position=;

}

server = servicesList.get(position);

position++;

}

returnserver;

}

public static voidmain(String[]args) {

while(true){

}

}

}

随机算法:

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

实现也很简单:

如下:

public classRandomDemo{

public staticListinitServerList() {

List servers =newArrayList();

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");

returnservers;

}

public staticStringgetServerUrl() {

//新建立一个List赋值,避免服务器上下线导致的并发问题

List serverList =newArrayList();

serverList.addAll(initServerList());

intposition =newRandom().nextInt(serverList.size());

returnserverList.get(position);

}

public static voidmain(String[]args) {

while(true) {

}

}

}

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

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

这就有了

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

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

代码实现:

public classHashDemo{

public staticListinitServerList() {

List servers =newArrayList();

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");

returnservers;

}

public staticStringgetServerUrl() {

//新建立一个List赋值,避免服务器上下线导致的并发问题

List serverList =newArrayList();

serverList.addAll(initServerList());

intrequestIpHashCode ="192.168.10.06.109".hashCode();

intposition = requestIpHashCode % serverList.size();

returnserverList.get(position);

}

public static voidmain(String[]args) {

while(true) {

}

}

}

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180617G0U80900?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码关注腾讯云开发者

领取腾讯云代金券