上一篇看到,在执行LoadBalancerInterceptor.intercept拦截器方法的时候,会调用LoadBalancerClient.execute方法,
即RibbonLoadBalancerClient.execute方法
public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException {
ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId);
Server server = this.getServer(loadBalancer, hint);
if(server == null) {
throw new IllegalStateException("No instances available for " + serviceId);
} else {
RibbonLoadBalancerClient.RibbonServer ribbonServer = new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server));
return this.execute(serviceId, (ServiceInstance)ribbonServer, (LoadBalancerRequest)request);
}
}
根据serviceId(服务名称)获得ILoadBalancer 实例(每个服务名称都会对应一个ILoadBalancer 实例),然后通过ILoadBalancer 的负载均衡策略选择合适的服务器。那么ILoadBalancer 是如何初始化的,如何找到对应服务的ILoadBalancer ?
public <C> C getInstance(String name, Class<C> type) {
Object instance = super.getInstance(name, type);
if(instance != null) {
return instance;
} else {
IClientConfig config = (IClientConfig)this.getInstance(name, IClientConfig.class);
return instantiateWithConfig(this.getContext(name), type, config);
}
}
查看RibbonLoadBalancerClient.getLoadBalancer方法,它会调用SpringClientFactory.getInstance方法获取的LoadBalancer实例,整个context 的实例化过程是在SpringClientFactory的父类NamedContextFactory中完成的
public <T> T getInstance(String name, Class<T> type) {
AnnotationConfigApplicationContext context = this.getContext(name);
return BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, type).length > 0?context.getBean(type):null;
}
protected AnnotationConfigApplicationContext getContext(String name) {
if(!this.contexts.containsKey(name)) {
Map var2 = this.contexts;
synchronized(this.contexts) {
if(!this.contexts.containsKey(name)) {
//创建容器,并以服务名称为key,保存在contexts的Map结构中
this.contexts.put(name, this.createContext(name));
}
}
}
return (AnnotationConfigApplicationContext)this.contexts.get(name);
}
protected AnnotationConfigApplicationContext createContext(String name) {
//创建context 对象,相当于重新新建了一个Spring容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
if(this.configurations.containsKey(name)) {
Class[] var3 = ((NamedContextFactory.Specification)this.configurations.get(name)).getConfiguration();
int entry = var3.length;
for(int var5 = 0; var5 < entry; ++var5) {
Class configuration = var3[var5];
context.register(new Class[]{configuration});
}
}
Iterator var9 = this.configurations.entrySet().iterator();
while(true) {
Entry var10;
do {
if(!var9.hasNext()) {
/**向容器中注册PropertyPlaceholderAutoConfiguration和defaultConfigType(org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration)**/
context.register(new Class[]{PropertyPlaceholderAutoConfiguration.class, this.defaultConfigType});
//设置环境变量ribbon.client.name的值
context.getEnvironment().getPropertySources().addFirst(new MapPropertySource(this.propertySourceName, Collections.singletonMap(this.propertyName, name)));
if(this.parent != null) {
context.setParent(this.parent);
context.setClassLoader(this.parent.getClassLoader());
}
context.setDisplayName(this.generateDisplayName(name));
//初始化容器
context.refresh();
return context;
}
var10 = (Entry)var9.next();
} while(!((String)var10.getKey()).startsWith("default."));
Class[] var11 = ((NamedContextFactory.Specification)var10.getValue()).getConfiguration();
int var12 = var11.length;
for(int var7 = 0; var7 < var12; ++var7) {
Class configuration1 = var11[var7];
context.register(new Class[]{configuration1});
}
}
}
在NamedContextFactory.getInstance方法中首先会去调用自己的getContext方法获取context,如果contexts的Map结构存在对应服务名称的context则返回,否则调用createContext方法创建AnnotationConfigApplicationContext,并以name(服务名称)为key,保存到contexts的Map结构中。在NamedContextFactory.createContext中,会创建AnnotationConfigApplicationContext,并设置需要注册到这个小型Spring容器中的Class类,即PropertyPlaceholderAutoConfiguration和defaultConfigType(RibbonClientConfiguration)两个对象,容器的环境变量ribbon.client.name(就是服务的名称,用于给RibbonClientConfiguration.name变量赋值,RibbonClientConfiguration.name变量上有一个@RibbonClientName注解,进入注解里面发现其实就是@Value("${ribbon.client.name}"))。RibbonClientConfiguration是一个配置类,它实例化了ILoadBalancer、IClientConfig、IRule(负载均衡的算法规则)、IPing(ping ip的规则)、ServerList<Server>、ServerListUpdater等,获取到context之后,通过context.getBean方法获得ILoadBalancer对象。
protected Server getServer(ILoadBalancer loadBalancer, Object hint) {
return loadBalancer == null?null:loadBalancer.chooseServer(hint != null?hint:"default");
}
protected Server getServer(ILoadBalancer loadBalancer, Object hint) {
return loadBalancer == null?null:loadBalancer.chooseServer(hint != null?hint:"default");
}
public Server chooseServer(Object key) {
if(this.counter == null) {
this.counter = this.createCounter();
}
this.counter.increment();
if(this.rule == null) {
return null;
} else {
try {
return this.rule.choose(key);
} catch (Exception var3) {
logger.warn("LoadBalancer [{}]: Error choosing server for key {}", new Object[]{this.name, key, var3});
return null;
}
}
}
回到RibbonLoadBalancerClient.execute方法,获取到服务名称对应的ILoadBalancer后,调用RibbonLoadBalancerClient.getServer方法,即通过BaseLoadBalancer.chooseServer方法选择合适的服务器,BaseLoadBalancer.chooseServer通过调用配置的IRule实现类的choose方法,选择合适的服务器。
ILoadBalancer选择服务器的逻辑基本看完,那么每个ILoadBalancer的服务器列表是如何维护的?当某个服务器下线了,ILoadBalancer如何将它从可用的服务器列表中删除?
以DynamicServerListLoadBalancer为例,
public DynamicServerListLoadBalancer(IClientConfig clientConfig, IRule rule, IPing ping, ServerList<T> serverList, ServerListFilter<T> filter, ServerListUpdater serverListUpdater) {
super(clientConfig, rule, ping);
this.isSecure = false;
this.useTunnel = false;
this.serverListUpdateInProgress = new AtomicBoolean(false);
this.updateAction = new UpdateAction() {//更新服务器列表的操作类
public void doUpdate() {
DynamicServerListLoadBalancer.this.updateListOfServers();
}
};
this.serverListImpl = serverList;
this.filter = filter;
this.serverListUpdater = serverListUpdater;
if(filter instanceof AbstractServerListFilter) {
((AbstractServerListFilter)filter).setLoadBalancerStats(this.getLoadBalancerStats());
}
this.restOfInit(clientConfig);
}
void restOfInit(IClientConfig clientConfig) {
boolean primeConnection = this.isEnablePrimingConnections();
this.setEnablePrimingConnections(false);
this.enableAndInitLearnNewServersFeature();
this.updateListOfServers();
if(primeConnection && this.getPrimeConnections() != null) {
this.getPrimeConnections().primeConnections(this.getReachableServers());
}
this.setEnablePrimingConnections(primeConnection);
LOGGER.info("DynamicServerListLoadBalancer for client {} initialized: {}", clientConfig.getClientName(), this.toString());
}
public void enableAndInitLearnNewServersFeature() {
LOGGER.info("Using serverListUpdater {}", this.serverListUpdater.getClass().getSimpleName());
this.serverListUpdater.start(this.updateAction);
}
在DynamicServerListLoadBalancer的构造方法中,初始化了UpdateAction这个更新服务列表的操作类,然后调用restOfInit方法,在restOfInit调用enableAndInitLearnNewServersFeature,通过serverListUpdater.start开启了一个定时器,用于定时执行updateAction.doUpdate操作,更新服务器列表,serverListUpdater(PollingServerListUpdater)是在RibbonClientConfiguration.ribbonServerListUpdater中初始化的
public void enableAndInitLearnNewServersFeature() {
LOGGER.info("Using serverListUpdater {}", this.serverListUpdater.getClass().getSimpleName());
this.serverListUpdater.start(this.updateAction);
}
public synchronized void start(final UpdateAction updateAction) {
if(this.isActive.compareAndSet(false, true)) {
Runnable wrapperRunnable = new Runnable() {
public void run() {
if(!PollingServerListUpdater.this.isActive.get()) {
if(PollingServerListUpdater.this.scheduledFuture != null) {
PollingServerListUpdater.this.scheduledFuture.cancel(true);
}
} else {
try {
updateAction.doUpdate();
PollingServerListUpdater.this.lastUpdated = System.currentTimeMillis();
} catch (Exception var2) {
PollingServerListUpdater.logger.warn("Failed one update cycle", var2);
}
}
}
};
this.scheduledFuture = getRefreshExecutor().scheduleWithFixedDelay(wrapperRunnable, this.initialDelayMs, this.refreshIntervalMs, TimeUnit.MILLISECONDS);
} else {
logger.info("Already active, no-op");
}
}
查看PollingServerListUpdater.start方法,其创建了一个定时器,默认每隔30秒去执行updateAction.doUpdate()方法,updateAction是在DynamicServerListLoadBalancer的构造函数中创建的,其实就是调用了
DynamicServerListLoadBalancer.this.updateListOfServers()方法
@VisibleForTesting
public void updateListOfServers() {
Object servers = new ArrayList();
if(this.serverListImpl != null) {
servers = this.serverListImpl.getUpdatedListOfServers();
LOGGER.debug("List of Servers for {} obtained from Discovery client: {}", this.getIdentifier(), servers);
if(this.filter != null) {
servers = this.filter.getFilteredListOfServers((List)servers);
LOGGER.debug("Filtered List of Servers for {} obtained from Discovery client: {}", this.getIdentifier(), servers);
}
}
this.updateAllServerList((List)servers);
}
protected void updateAllServerList(List<T> ls) {
if(this.serverListUpdateInProgress.compareAndSet(false, true)) {
try {
Iterator var2 = ls.iterator();
while(var2.hasNext()) {
Server s = (Server)var2.next();
s.setAlive(true);
}
//设置allServerList所有的服务器列表
this.setServersList(ls);
//通过IPingStrategy策略,设置upServerList可用的服务器列表
super.forceQuickPing();
} finally {
this.serverListUpdateInProgress.set(false);
}
}
}
public void setServersList(List lsrv) {
//调用父类BaseLoadBalancer的setServersList,设置allServerList所有的服务器列表
super.setServersList(lsrv);
HashMap serversInZones = new HashMap();
Iterator var4 = lsrv.iterator();
while(var4.hasNext()) {
Server server = (Server)var4.next();
this.getLoadBalancerStats().getSingleServerStat(server);
String zone = server.getZone();
if(zone != null) {
zone = zone.toLowerCase();
Object servers = (List)serversInZones.get(zone);
if(servers == null) {
servers = new ArrayList();
serversInZones.put(zone, servers);
}
((List)servers).add(server);
}
}
this.setServerListForZones(serversInZones);
}
在updateListOfServers方法中首先调用serverListImpl(ConfigurationBasedServerList)的getUpdatedListOfServers方法,获取所有的服务类列表,然后调用ConfigurationBasedServerList.updateAllServerList方法,ConfigurationBasedServerList.updateAllServerList最终会调用BaseLoadBalancer.setServersList设置allServerList(所有的服务器列表),回到DynamicServerListLoadBalancer.updateAllServerList方法,设置完allServerList后继续调用super.forceQuickPing(即BaseLoadBalancer.setServersList)方法,通过ping ip的策略,设置upServerList(可用的服务列表)。