Soul 源码解析(一):Soul网关里的负载均衡策略
负载均衡
类结构
- 我们定义了一个AbstractLoadBalance抽象类,抽象类主要实现了select方法,以及定义了一个doSelect方法(实现类通过重写doSelect完成各种负载均衡策略);
- 定义了三个不同策略的负载均衡策略来实现AbstractLoadBalance抽象类的doSelect方法,从而实现负载均衡的处理;
Soul源码的负载均衡算法的目录位置如图所示,进入工程的下面目录即可找到Soul的负载均衡源码;
Soul网关支持的负载均衡策略
- Hash算法
- 随机 & 加权随机
- 轮询
下面我们一起看下随机&加权随机负载均衡的实现过程:
随机&加权随机
随机
加权随机
在使用加权随机负载均衡时,我们会在Soul 的Admin控制台配置各个服务器的权重; 处理过程:
- 计算所有服务器的总权重;
- 判断所有服务器的请求是否一致,如果都一致,直接采用随机策略;
package org.dromara.soul.plugin.divide.balance.spi; import org.dromara.soul.common.dto.convert.DivideUpstream; import org.dromara.soul.spi.Join; import java.util.List; import java.util.Random; /** * random algorithm impl. * * @author xiaoyu(Myth) */ @Join public class RandomLoadBalance extends AbstractLoadBalance { private static final Random RANDOM = new Random(); @Override public DivideUpstream doSelect(final List<DivideUpstream> upstreamList, final String ip) { int totalWeight = calculateTotalWeight(upstreamList); boolean sameWeight = isAllUpStreamSameWeight(upstreamList); if (totalWeight > 0 && !sameWeight) { return random(totalWeight, upstreamList); } // If the weights are the same or the weights are 0 then random return random(upstreamList); } private boolean isAllUpStreamSameWeight(final List<DivideUpstream> upstreamList) { boolean sameWeight = true; int length = upstreamList.size(); for (int i = 0; i < length; i++) { int weight = getWeight(upstreamList.get(i)); if (i > 0 && weight != getWeight(upstreamList.get(i - 1))) { // Calculate whether the weight of ownership is the same sameWeight = false; break; } } return sameWeight; } private int calculateTotalWeight(final List<DivideUpstream> upstreamList) { // total weight int totalWeight = 0; for (DivideUpstream divideUpstream : upstreamList) { int weight = getWeight(divideUpstream); // Cumulative total weight totalWeight += weight; } return totalWeight; } private DivideUpstream random(final int totalWeight, final List<DivideUpstream> upstreamList) { // If the weights are not the same and the weights are greater than 0, then random by the total number of weights int offset = RANDOM.nextInt(totalWeight); // Determine which segment the random value falls on for (DivideUpstream divideUpstream : upstreamList) { offset -= getWeight(divideUpstream); if (offset < 0) { return divideUpstream; } } return upstreamList.get(0); } private DivideUpstream random(final List<DivideUpstream> upstreamList) { return upstreamList.get(RANDOM.nextInt(upstreamList.size())); } }