eureka client自己本身,是不断的去从eureka server每隔30秒更新一次注册表,拉取增量注册表。所以说ribbon和eureka整合的机制里,肯定得有一个组件,负责每隔一定的时间,从本地的eureka client里刷新一下服务的注册表到LoadBalancer中。。。
(1)调用PollingServerListUpdater实现类的start方法启动一个定时线程
public class DynamicServerListLoadBalancer<T extends Server> extends BaseLoadBalancer {
/**
* 实现了ServerListUpdater的UpdateAction()方法,直接调用updateListOfServers()来更新注册表
* 其实就是从eureka client里去获取一下注册表,重新更新到LoadBalancer中去
*/
protected final ServerListUpdater.UpdateAction updateAction = new ServerListUpdater.UpdateAction() {
@Override
public void doUpdate() {
updateListOfServers();
}
};
void restOfInit(IClientConfig clientConfig) {
boolean primeConnection = this.isEnablePrimingConnections();
// turn this off to avoid duplicated asynchronous priming done in BaseLoadBalancer.setServerList()
this.setEnablePrimingConnections(false);
/**
* 启动一个定时线程,每30s更新一次ServiceA的server list
* 就去从eureka client刷新注册表到自己的ribbon的LoadBalancer中来
*/
enableAndInitLearnNewServersFeature();
//从eureka client那里获取到ServiceA的server list
updateListOfServers();
if (primeConnection && this.getPrimeConnections() != null) {
this.getPrimeConnections()
.primeConnections(getReachableServers());
}
this.setEnablePrimingConnections(primeConnection);
LOGGER.info("DynamicServerListLoadBalancer for client {} initialized: {}", clientConfig.getClientName(), this.toString());
}
public void enableAndInitLearnNewServersFeature() {
LOGGER.info("Using serverListUpdater {}", serverListUpdater.getClass().getSimpleName());
//调用PollingServerListUpdater实现类的start方法启动一个定时线程
serverListUpdater.start(updateAction);
}
@VisibleForTesting
public void updateListOfServers() {
List<T> servers = new ArrayList<T>();
if (serverListImpl != null) {
//真正调用的是DiscoveryEnabledNIWSServerList实现类的getUpdatedListOfServers()方法
servers = serverListImpl.getUpdatedListOfServers();
LOGGER.debug("List of Servers for {} obtained from Discovery client: {}",
getIdentifier(), servers);
if (filter != null) {
//从一个服务中过滤掉某些server,不要去访问那些server
servers = filter.getFilteredListOfServers(servers);
LOGGER.debug("Filtered List of Servers for {} obtained from Discovery client: {}",
getIdentifier(), servers);
}
}
//将从eurekaclient获取的servers列表设置进BaseLoadBalancer的服务实例列表allServerList,这将覆盖原有服务器列表。
updateAllServerList(servers);
}
}
(2)给PollingServerListUpdater的start()方法传入了一个UpdateAction,代表的是实际的更新注册表的行为。。。其实呢,每次PollingServerListUpdater定时更新注册表的时候,执行的实际的行为,就是上一篇博客看到的那个updateListOfServers()方法,其实就是从eureka client里去获取一下注册表,重新更新到LoadBalancer中去。。。。
在PollingServerListUpdater中,创建了一个Runnable线程,里面就是执行UpdateAction的行为。默认的是1秒钟过后,会第一次执行那个Runnable线程,以后是每隔30秒执行一下那个Runnable线程,就去从eureka client刷新注册表到自己的ribbon的LoadBalancer中来。
public class PollingServerListUpdater implements ServerListUpdater {
@Override
public synchronized void start(final UpdateAction updateAction) {
if (isActive.compareAndSet(false, true)) {
//创建了一个Runnable线程,里面就是执行UpdateAction的行为
final Runnable wrapperRunnable = new Runnable() {
@Override
public void run() {
if (!isActive.get()) {
if (scheduledFuture != null) {
scheduledFuture.cancel(true);
}
return;
}
try {
/**
* updateAction其实是直接调用updateListOfServers()
* 其实就是从eureka client里去获取一下注册表,重新更新到LoadBalancer中去
*/
updateAction.doUpdate();
lastUpdated = System.currentTimeMillis();
} catch (Exception e) {
logger.warn("Failed one update cycle", e);
}
}
};
/**
* 默认的是1秒钟过后,会第一次执行那个Runnable线程,以后是每隔30秒执行一下那个Runnable线程,
* 就去从eureka client刷新注册表到自己的ribbon的LoadBalancer中来。
*/
scheduledFuture = getRefreshExecutor().scheduleWithFixedDelay(
wrapperRunnable,
initialDelayMs,
refreshIntervalMs,
TimeUnit.MILLISECONDS
);
} else {
logger.info("Already active, no-op");
}
}
}
总结:ribbon如何持续的从eureka中获取注册表 流程图