¡Acostúmbrate a escribir juntos! Este es el día 13 de mi participación en el "Desafío de actualización de abril del nuevo plan diario de Nuggets", haga clic para ver los detalles del evento
Diagrama + código fuente para explicar la actualización de la lista de servicios de Ribbon
La diligencia es el factor decisivo para el genio - Guo Moruo
Artículos relacionados
Ilustración + Código fuente Explicación de la cinta Cómo obtener el Centro de registro Ejemplo
Ilustración + Código fuente Explicación de los principios de la cinta
Equilibrador de carga de servicio dinámico DynamicServerListLoadBalancer
Hay un método restOfInit en este balanceador de carga.Este método implica extraer la lista de servicios del registro y extraer o monitorear los cambios de la lista de actualización, y luego configurarlo en el balanceador de carga y proporcionarlo al tiempo de ejecución de la solicitud. una selección de servicios
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);
}
复制代码
En este método, enableAndInitLearnNewServersFeature es un método central que se utiliza para realizar una lista de cambios de servicio de extracción o supervisión específica.
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());
}
复制代码
Operación de cambio de lista de servicios enableAndInitLearnNewServersFeature
Habilitar la operación de notificación de actualización de cambio de lista de servicios
public void enableAndInitLearnNewServersFeature() {
// 服务列表更新器开启 updateAction 更新操作
serverListUpdater.start(updateAction);
}
复制代码
protected final ServerListUpdater.UpdateAction updateAction =
new ServerListUpdater.UpdateAction() {
@Override
public void doUpdate() {
// 这个就是上面讲解的服务实例拉取操作
updateListOfServers();
}
};
复制代码
Política de cambio de lista de servicios
Estrategia de extracción cronometrada
El método serverListUpdater.start tiene dos estrategias de implementación, una es la operación de notificación de servicio eureka, la otra es la operación de cambio de servicio de extracción activa, el valor predeterminado es la estrategia de servicio de actualización PollingServerListUpdater [la estrategia PollingServerListUpdater se ha creado en RibbonClientConfiguration] como se muestra a continuación
@Bean
@ConditionalOnMissingBean
public ServerListUpdater ribbonServerListUpdater(IClientConfig config) {
return new PollingServerListUpdater(config);
}
复制代码
Extraiga periódicamente la lista de servicios actualizada PollingServerListUpdater
30s para extraer la lista de servicios una vez para ver si la lista de servicios ha cambiado
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 方法
Se creó un programador de subprocesos para ejecutar la tarea wrapperRunnable con un retraso y una frecuencia fijos.
@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() actualiza periódicamente la lista de servicios
updateAction es la UpdateAction pasada en el método enableAndInitLearnNewServersFeature() anterior De hecho, es para llamar al método updateListOfServers() regularmente para actualizar la lista de servicios.
protected final ServerListUpdater.UpdateAction updateAction = new ServerListUpdater.UpdateAction() {
@Override
public void doUpdate() {
updateListOfServers();
}
};
复制代码
Estrategia de monitoreo del servicio
Actualizador de la lista del servicio de notificaciones de Eureka 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() Este método es el mismo que el seguimiento anterior
resumen
- Dos formas de actualizar la lista de servicios
- Una es extraer y actualizar periódicamente la operación de la lista.
- Uno es el evento de notificación de actualización de caché eureka para actualizar la lista de servicios