Java负载均衡的实现原理

76 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第29天,点击查看活动详情

1、负载均衡算法简介和实现

1.1、随机

通过随机算法,根据后端服务器的列表随机选取其中的一台服务器进行访问

@Component
public class RandomStrategy implements LoadBalanceStrategy {

	@Override
	public String load(List<String> uris) {
		// 0~bound(不包含)之间的随机数
		int randomNumber = new Random().nextInt(uris.size());
		return uris.get(randomNumber);
	}
}

1.2、轮询

将请求按顺序轮流地分配到后端服务器上,它均衡地对待后端的每一台服务器,而不关心服务器实际的连接数和当前的系统负载;

@Component
public class RoundRobinStrategy implements LoadBalanceStrategy {

	/**
	 * 定义原子计数类
	 */
	private AtomicInteger index = new AtomicInteger(0);

	@Override
	public String load(List<String> uris) {
		return uris.get(Math.abs(index.incrementAndGet() % uris.size()));
	}
}

1.3、加权随机

加权随机法根据后端机器的配置,系统的负载分配不同的权重。随机获取服务器进行转发请求,本质上就是按照权重往列表多放了数据,但是还是随机的。

@Component
public class RandomWeightStrategy implements LoadBalanceStrategy {

	@Override
	public String load(List<String> uris) {
		// 0~bound(不包含)之间的随机数
		int randomNumber = new Random().nextInt(uris.size());
		return uris.get(randomNumber);
	}


	public String load(List<String> uris,List<Integer> weights) {
		// 构建加权list
		List<String> weightUris = new ArrayList<>();
		if(uris.size() != weights.size()){
			throw new RuntimeException("转发服务器列表需和权重列表数量一致");
		}

		for (int i = 0; i < uris.size(); i++) {
			Integer weight = weights.get(i);
			if(weight<=0){
				continue;
			}
			for (int j = 0; j < weight; j++) {
				weightUris.add(uris.get(i));
			}
		}

		// 0~bound(不包含)之间的随机数
		int randomNumber = new Random().nextInt(weightUris.size());
		return uris.get(randomNumber);
	}
}

1.4、加权轮询

同的后端服务器可能机器的配置和当前系统的负载并不相同,因此它们的抗压能力也不相同。给配置高、负载低的机器配置更高的权重,让其处理更多的请;而配置低、负载高的机器,给其分配较低的权重,降低其系统负载,加权轮询能很好地处理这一问题,并将请求顺序且按照权重分配到后端;

public class RoundRobinWeightStrategy implements LoadBalanceStrategy{

	/**
	 * 定义原子计数类
	 */
	private AtomicInteger index = new AtomicInteger(0);

	@Override
	public String load(List<String> uris) {
		return uris.get(Math.abs(index.incrementAndGet() % uris.size()));
	}


	public String load(List<String> uris,List<Integer> weights) {
		// 构建加权list
		List<String> weightUris = new ArrayList<>();
		if(uris.size() != weights.size()){
			throw new RuntimeException("转发服务器列表需和权重列表数量一致");
		}

		for (int i = 0; i < uris.size(); i++) {
			Integer weight = weights.get(i);
			if(weight<=0){
				continue;
			}
			for (int j = 0; j < weight; j++) {
				weightUris.add(uris.get(i));
			}
		}

		return uris.get(Math.abs(index.incrementAndGet() % uris.size()));
	}

}

1.5、IpHash

通过请求ip进行hash,可以让服务器列表处理请求更加均衡

@Component
public class IpHashStrategy implements LoadBalanceStrategy {

	@Override
	public String load(List<String> uris) {
		return null;
	}

	public String load(List<String> uris, String ip) {
		return uris.get(ip.hashCode() % uris.size());
	}
}