Get into the habit of writing together! This is the 13th day of my participation in the "Nuggets Daily New Plan·April Update Challenge", click to view the event details
Diagram + source code to explain Ribbon service list update
Diligence is the decisive factor for genius - Guo Moruo
Related Articles
Illustration + Source Code Explaining Ribbon How to Get the Registration Center Example
Illustration + Source Code Explaining Ribbon Principles
Dynamic Service Load Balancer DynamicServerListLoadBalancer
There is a restOfInit method in this load balancer. This method involves pulling the service list of the registry, and pulling or monitoring the changes of the update list, and then setting it in the load balancer and providing it to the request execution time. Make a service selection
public DynamicServerListLoadBalancer(IClientConfig clientConfig, IRule rule,
IPing ping, ServerList<T> serverList, ServerListFilter<T> filter,
ServerListUpdater serverListUpdater) {
super(clientConfig, rule, ping);
this.serverListImpl = serverList;
this.filter = filter;
this.serverListUpdater = serverListUpdater;
if (filter instanceof AbstractServerListFilter) {
((AbstractServerListFilter) filter).
setLoadBalancerStats(getLoadBalancerStats());
}
// 核心方法,其他的方法先不细看
restOfInit(clientConfig);
}
复制代码
In this method, enableAndInitLearnNewServersFeature is a core method used to perform specified pull or monitor service change list
void restOfInit(IClientConfig clientConfig) {
boolean primeConnection = this.isEnablePrimingConnections();
// turn this off to avoid duplicated asynchronous priming done in BaseLoadBalancer.setServerList()
this.setEnablePrimingConnections(false);
enableAndInitLearnNewServersFeature();
updateListOfServers();
if (primeConnection && this.getPrimeConnections() != null) {
this.getPrimeConnections()
.primeConnections(getReachableServers());
}
this.setEnablePrimingConnections(primeConnection);
LOGGER.info("DynamicServerListLoadBalancer for client {} initialized: {}", clientConfig.getClientName(), this.toString());
}
复制代码
Service list change operation enableAndInitLearnNewServersFeature
Enable service list change update notification operation
public void enableAndInitLearnNewServersFeature() {
// 服务列表更新器开启 updateAction 更新操作
serverListUpdater.start(updateAction);
}
复制代码
protected final ServerListUpdater.UpdateAction updateAction =
new ServerListUpdater.UpdateAction() {
@Override
public void doUpdate() {
// 这个就是上面讲解的服务实例拉取操作
updateListOfServers();
}
};
复制代码
Service List Change Policy
Timed pull strategy
The serverListUpdater.start method has two implementation strategies, one is eureka service notification operation, the other is active pull service change operation, the default is PollingServerListUpdater update service strategy [PollingServerListUpdater strategy has been created in RibbonClientConfiguration] as shown below
@Bean
@ConditionalOnMissingBean
public ServerListUpdater ribbonServerListUpdater(IClientConfig config) {
return new PollingServerListUpdater(config);
}
复制代码
Regularly pull the updated service list PollingServerListUpdater
30s to pull the service list once to see if the service list has changed
private static long LISTOFSERVERS_CACHE_UPDATE_DELAY = 1000; // msecs;
// 30s 去拉取一次
private static int LISTOFSERVERS_CACHE_REPEAT_INTERVAL = 30 * 1000; // msecs;
public PollingServerListUpdater() {
this(LISTOFSERVERS_CACHE_UPDATE_DELAY, LISTOFSERVERS_CACHE_REPEAT_INTERVAL);
}
public PollingServerListUpdater(final long initialDelayMs, final long refreshIntervalMs) {
this.initialDelayMs = initialDelayMs;
this.refreshIntervalMs = refreshIntervalMs;
}
复制代码
PollingServerListUpdater#start 方法
Created a thread scheduler scheduledFuture to execute the wrapperRunnable task with a fixed delay and frequency
@Override
public synchronized void start(final UpdateAction updateAction) {
// 创建一个线程
final Runnable wrapperRunnable = new Runnable() {
@Override
public void run() {
if (!isActive.get()) {
if (scheduledFuture != null) {
scheduledFuture.cancel(true);
}
return;
}
try {
updateAction.doUpdate();
lastUpdated = System.currentTimeMillis();
} catch (Exception e) {
logger.warn("Failed one update cycle", e);
}
}
};
// 线程调度器调度 wrapperRunnable 任务
scheduledFuture = getRefreshExecutor().scheduleWithFixedDelay(
wrapperRunnable,
initialDelayMs,
refreshIntervalMs,
TimeUnit.MILLISECONDS
);
}
复制代码
updateAction.doUpdate() regularly updates the service list
updateAction is the UpdateAction passed in the previous enableAndInitLearnNewServersFeature() method. In fact, it is to call the updateListOfServers() method regularly to update the service list.
protected final ServerListUpdater.UpdateAction updateAction = new ServerListUpdater.UpdateAction() {
@Override
public void doUpdate() {
updateListOfServers();
}
};
复制代码
Service monitoring strategy
Eureka Notification Service List Updater EurekaNotificationServerListUpdater
// eureka事件监听器
private volatile EurekaEventListener updateListener;
// eureka 客户端
private volatile EurekaClient eurekaClient;
public EurekaNotificationServerListUpdater() {
this(new LegacyEurekaClientProvider());
}
public EurekaNotificationServerListUpdater(final Provider<EurekaClient>
eurekaClientProvider) {
this(eurekaClientProvider, getDefaultRefreshExecutor());
}
// 构造 eureka通知服务列表监听器
public EurekaNotificationServerListUpdater(final Provider<EurekaClient>
eurekaClientProvider, ExecutorService refreshExecutor) {
this.eurekaClientProvider = eurekaClientProvider;
this.refreshExecutor = refreshExecutor;
}
复制代码
EurekaNotificationServerListUpdater#start 方法
public synchronized void start(final UpdateAction updateAction) {
if (isActive.compareAndSet(false, true)) {
// 创建了一个eureka事件监听器
this.updateListener = new EurekaEventListener() {
@Override
public void onEvent(EurekaEvent event) {
// 缓存刷新事件
if (event instanceof CacheRefreshedEvent) {
if (!refreshExecutor.isShutdown()) {
refreshExecutor.submit(new Runnable() {
@Override
public void run() {
try {
// 进行服务列表更新
updateAction.doUpdate();
lastUpdated.set(System.currentTimeMillis());
} catch (Exception e) {
logger.warn("Failed to update serverList", e);
} finally {
updateQueued.set(false);
}
}
});
}
else {
stop();
}
}
}
};
if (eurekaClient == null) {
// 获取 eureka 客户端
eurekaClient = eurekaClientProvider.get();
}
if (eurekaClient != null) {
// 注册监听器
eurekaClient.registerEventListener(updateListener);
}
}
复制代码
updateAction.doUpdate() This method is the same as the follow-up above
summary
- Two ways to update the service list
- One is to periodically pull and update the list operation
- One is the eureka cache refresh notification event to update the service list