本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。
9负载均衡器之AbstractLoadBalancer
AbstractLoadBalancer
AbstractLoadBalancer是ILoadBalancer接口的抽象实现
public abstract class AbstractLoadBalancer implements ILoadBalancer {
public enum ServerGroup{
ALL,
STATUS_UP,
STATUS_NOT_UP
}
/**
* delegate to {@link #chooseServer(Object)} with parameter null.
*/
public Server chooseServer() {
return chooseServer(null);
}
/**
* List of servers that this Loadbalancer knows about
*
* @param serverGroup Servers grouped by status, e.g., {@link ServerGroup#STATUS_UP}
*/
public abstract List<Server> getServerList(ServerGroup serverGroup);
/**
* Obtain LoadBalancer related Statistics
*/
public abstract LoadBalancerStats getLoadBalancerStats();
}
定义枚举类ServerGroup
- ALL 所有服务实例
- STATUS_UP:正常服务实例
- STATUS_NOT_UP:停止服务实例
抽象方法
getServerList(ServerGroup serverGroup):定义了根据分组类型来获取不同服务实例的列表
getLoadBalancerStats(); 定义获取LoadBalancerStats对象的方法,LoadBalancerStats对象被用来存储负载均衡器中各个服务实例当前的属性和统计信息。
BaseLoadBalancer
BaseLoadBalancer是Ribbon负载均衡器的基础实现类
-
定义并维护两个存储服务实例Server对象的列表,一个用于存储所有服务实例的清单,一个用于存储正常服务的实例清单
@Monitor(name = PREFIX + "AllServerList", type = DataSourceType.INFORMATIONAL) protected volatile List<Server> allServerList = Collections .synchronizedList(new ArrayList<Server>()); @Monitor(name = PREFIX + "UpServerList", type = DataSourceType.INFORMATIONAL) protected volatile List<Server> upServerList = Collections .synchronizedList(new ArrayList<Server>());
-
定义之前用来存储负载均衡器各服务实例属性和统计信息的LoadBalancerStats对象。
-
定义了检查服务实例是否正常服务的IPing对象,在BaseLoadBalancer中默认为null,需要在构造时注入它的具体实现
-
定义了检查服务实例操作的执行策略对象IPingStrategy,默认使用了该类中定义的静态内部类
private static class SerialPingStrategy implements IPingStrategy {
@Override
public boolean[] pingServers(IPing ping, Server[] servers) {
int numCandidates = servers.length;
boolean[] results = new boolean[numCandidates];
if (logger.isDebugEnabled()) {
logger.debug("LoadBalancer: PingTask executing ["
+ numCandidates + "] servers configured");
}
for (int i = 0; i < numCandidates; i++) {
results[i] = false; /* Default answer is DEAD. */
try {
// NOTE: IFF we were doing a real ping
// assuming we had a large set of servers (say 15)
// the logic below will run them serially
// hence taking 15 times the amount of time it takes
// to ping each server
// A better method would be to put this in an executor
// pool
// But, at the time of this writing, we dont REALLY
// use a Real Ping (its mostly in memory eureka call)
// hence we can afford to simplify this design and run
// this
// serially
if (ping != null) {
results[i] = ping.isAlive(servers[i]);
}
} catch (Throwable t) {
logger.error("Exception while pinging Server:"
+ servers[i], t);
}
}
return results;
}
}
- 定义负载均衡的处理规则IRule对象,负载均衡器实际将服务实例选择任务委托给IRule实例的choose方法来实现,默认初始化RoundRobinRule为IRule实现对象,RoundRobinRule实现了基本的线性负载均衡规则。
public Server chooseServer(Object key) {
if (counter == null) {
counter = createCounter();
}
counter.increment();
if (rule == null) {
return null;
} else {
try {
return rule.choose(key);
} catch (Throwable t) {
return null;
}
}
}
启动ping任务:BaseLoadBalancer默认构造方法中,直接启动一个用于定时检查Server是否健康的任务。任务默认执行间隔为10s
实现ILoadBalancer接口:
chooseServer方法
addServers方法:
public void addServers(List<Server> newServers) {
if (newServers != null && newServers.size() > 0) {
try {
ArrayList<Server> newList = new ArrayList<Server>();
newList.addAll(allServerList);
newList.addAll(newServers);
setServersList(newList);
} catch (Exception e) {
logger.error("Exception while adding Servers", e);
}
}
}
getReachableServers方法:获取可用的服务实例列表
public List<Server> getReachableServers() {
return Collections.unmodifiableList(upServerList);
}
单独维护一个正常服务的实例清单,直接返回即可
getAllServers方法:获取所有服务实例列表
@Override
public List<Server> getAllServers() {
return Collections.unmodifiableList(allServerList);
}