负载均衡
负载均衡是实现分布式系统高可用的方式之一;负载均衡策略实现了把高并发的流量分摊在其后的服务器集群上;常见的,有基于F5硬件负载均衡设备、基于DNS的负载均衡设备(根据请求IP,选择就近的服务集群提供服务,DNS的缓存不能使负载均衡策略立即生效)、基于软件LVS的负载均衡设备(分两种:七层应用层的Nginx负载均衡、四层传输层的流量分发)。
负载均衡算法
常见负载均衡算法有:轮询策略(顺序轮询和随机轮询)、负载度策略、响应策略、哈希策略。实际项目中使用轮询策略的居多;
基于轮询策略的负载均衡算法实现
public interface LoadBalanceSelector<N, C> {
N select(C c);
}
@RequiredArgsConstructor
public abstract class AbstractLoadBalanceSelector<N, C> implements LoadBalanceSelector<N, C> {
private final Supplier<List<N>> supplier;
private final Predicate<N> predicate;
@Override
public N select(C c) {
List<N> candidates = supplier.get();
if (CollectionUtils.isEmpty(candidates)) {
return null;
} else if (candidates.size() == 1) {
return predicate.test(candidates.get(0)) ? candidates.get(0) : null;
}
N candidate = null;
int idx = getIndex(candidates);
for (int i = 0; i < candidates.size(); i++) {
N n = candidates.get((i + idx) % candidates.size());
if (predicate.test(n)) {
candidate = n;
}
}
return candidate;
}
abstract protected int getIndex(List<N> candidates);
}
public class RandomLoadBalanceSelector<N, C> extends AbstractLoadBalanceSelector<N, C> {
public RandomLoadBalanceSelector(Supplier<List<N>> supplier, Predicate<N> predicate) {
super(supplier, predicate);
}
@Override
protected int getIndex(List<N> candidates) {
return (int) (ThreadLocalRandom.current().nextDouble() * candidates.size());
}
}
public class RoundRobinLoadBalanceSelector<N, C> extends AbstractLoadBalanceSelector<N, C> {
private static AtomicInteger idx = new AtomicInteger(0);
public RoundRobinLoadBalanceSelector(Supplier<List<N>> supplier, Predicate<N> predicate) {
super(supplier, predicate);
}
@Override
protected int getIndex(List<N> candidates) {
return 0x7fffffff & idx.incrementAndGet();
}
}
public enum LoadBalanceStrategyEnums {
RoundRobin,
RANDOM,
}
public final class LoadBalanceSelectors {
private LoadBalanceSelectors() {
}
public static <N, C> LoadBalanceSelector<N, C> of(Supplier<List<N>> supplier, Predicate<N> predicate,
LoadBalanceStrategyEnums loadBalanceStrategy) {
if (loadBalanceStrategy == LoadBalanceStrategyEnums.RANDOM) {
return new RandomLoadBalanceSelector<N,C>(supplier, predicate);
}
return new RoundRobinLoadBalanceSelector<N,C>(supplier, predicate);
}
}
网友评论