负载均衡系列专题
01-负载均衡基础知识
02-一致性 hash 原理
03-一致性哈希算法 java 实现
04-负载均衡算法 java 实现
本节我们来看一下如何实现一负载均衡框架。
源码
核心接口定义
public interface ILoadBalance {
/*** 选择下一个节点** 返回下标* @param context 上下文* @return 结果* @since 0.0.1*/IServer select(final ILoadBalanceContext context);}
1. 随机策略
public class LoadBalanceRandom extends AbstractLoadBalance{
public LoadBalanceRandom(List<IServer> servers) {
super(servers);}@Overrideprotected IServer doSelect(ILoadBalanceContext context) {
Random random = ThreadLocalRandom.current();int nextIndex = random.nextInt(servers.size());return servers.get(nextIndex);}}
2. 轮训
public class LoadBalanceRoundRobbin extends AbstractLoadBalance {
/*** 位移指针* @since 0.0.1*/private final AtomicLong indexHolder = new AtomicLong();public LoadBalanceRoundRobbin(List<IServer> servers) {
super(servers);}@Overrideprotected IServer doSelect(ILoadBalanceContext context) {
long index = indexHolder.getAndIncrement();int actual = (int) (index % servers.size());return servers.get(actual);}}
3. 有权重的轮训
这个需要对数据进行初始化处理,计算数组的最大公约数。
public class LoadBalanceWeightRoundRobbin extends AbstractLoadBalance {
/*** 位移指针* @since 0.0.1*/private final AtomicLong indexHolder = new AtomicLong();/*** 处理后的列表* @since 0.0.1*/private final List<IServer> actualList = new ArrayList<>();public LoadBalanceWeightRoundRobbin(List<IServer> servers) {
super(servers);// 初始化真实列表this.init(servers);}@Overrideprotected IServer doSelect(ILoadBalanceContext context) {
long index = indexHolder.getAndIncrement();// 基于真实的列表构建int actual = (int) (index % actualList.size());return actualList.get(actual);}/*** 初始化* @param serverList 服务列表* @since 0.0.1*/private void init(final List<IServer> serverList) {
//1. 过滤掉权重为 0 的机器List<IServer> notZeroServers = CollectionUtil.filterList(serverList, new IFilter<IServer>() {
@Overridepublic boolean filter(IServer iServer) {
return iServer.weight() <= 0;}});//2. 获取权重列表List<Integer> weightList = CollectionUtil.toList(notZeroServers, new IHandler<IServer, Integer>() {
@Overridepublic Integer handle(IServer iServer) {
return iServer.weight();}});//3. 获取最大的权重int maxDivisor = MathUtil.ngcd(weightList);//4. 重新计算构建基于权重的列表for(IServer server : notZeroServers) {
int weight = server.weight();int times = weight / maxDivisor;for(int i = 0; i < times; i++) {
actualList.add(server);}}}}
4. 普通哈希
public class LoadBalanceCommonHash extends AbstractLoadBalanceHash {
public LoadBalanceCommonHash(List<IServer> servers, IHash hash) {
super(servers, hash);}@Overrideprotected IServer doSelect(ILoadBalanceContext context) {
final String hashKey = context.hashKey();int hashCode = Math.abs(hash.hash(hashKey));int index = servers.size() % hashCode;return servers.get(index);}}
5. 一致性哈希
这里将我们前面实现的一致性哈希,与负载均衡结合。
public class LoadBalanceConsistentHash extends AbstractLoadBalanceHash {
/*** 一致性 hash 实现* @since 0.0.1*/private final IConsistentHashing<IServer> consistentHashing;public LoadBalanceConsistentHash(List<IServer> servers, IHash hash) {
super(servers, hash);this.consistentHashing = ConsistentHashingBs.<IServer>newInstance().hash(hash).nodes(servers).build();}@Overrideprotected IServer doSelect(ILoadBalanceContext context) {
final String hashKey = context.hashKey();return consistentHashing.get(hashKey);}}
后期 Road-Map
还有基于系统最小压力,最小连接的实现,暂时没有放在这里。
后续将加入对应的实现。
完整开源代码
其他还有一些引导类等辅助工具。
完整代码参见 load-balance