Nacos+Springloadbalancer se da cuenta rápido en línea y fuera de línea

entorno de desarrollo

cuadro Versión
Nube primaveral 2020.0.2
Nacos 2.2.1.LIBERAR

Metas

Dado que loadbalancerel caché de equilibrio de carga predeterminado es de 30 s , si se produce un servicio 上下线, el consumidor del servicio no puede saber la adquisición en el primer momento y la llamada 远程服务fallará. Por lo tanto, queremos darnos cuenta de que cuando el servicio se desconecta, puede notificar al consumidor del servicio la primera vez y luego puede realizar una serie de operaciones.

Idea principal

Mi idea es usar Nacosla interfaz de transformación del servicio de monitoreo para modificar la lista de caché del equilibrio de carga para realizar la modificación en tiempo real de la lista de caché del servicio.

Leer el código fuente

org.springframework.cloud.loadbalancer.configSe encontraron dos clases al observar las clases de configuración en el paquete

@Configuration(proxyBeanMethods = false)
    @ConditionalOnClass({ Caffeine.class, CaffeineCacheManager.class })
    protected static class CaffeineLoadBalancerCacheManagerConfiguration {
​
        @Bean(autowireCandidate = false)
        @ConditionalOnMissingBean
        LoadBalancerCacheManager caffeineLoadBalancerCacheManager(LoadBalancerCacheProperties cacheProperties) {
            return new CaffeineBasedLoadBalancerCacheManager(cacheProperties);
        }
​
    }
​
    @Configuration(proxyBeanMethods = false)
    @Conditional(OnCaffeineCacheMissingCondition.class)
    @ConditionalOnClass(ConcurrentMapWithTimedEviction.class)
    protected static class DefaultLoadBalancerCacheManagerConfiguration {
​
        @Bean(autowireCandidate = false)
        @ConditionalOnMissingBean
        LoadBalancerCacheManager defaultLoadBalancerCacheManager(LoadBalancerCacheProperties cacheProperties) {
            return new DefaultLoadBalancerCacheManager(cacheProperties);
        }
​
    }

Se puede ver que, por defecto, Spring LoadBalancer utilizará la DefaultLoadBalancerCacheManagerclase de implementación como gestión de caché, así que echemos un vistazo a su código fuente.

public class DefaultLoadBalancerCacheManager implements LoadBalancerCacheManager {
​
    private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<>(16);
​
    public DefaultLoadBalancerCacheManager(LoadBalancerCacheProperties loadBalancerCacheProperties,
            String... cacheNames) {
        cacheMap.putAll(createCaches(cacheNames, loadBalancerCacheProperties).stream()
                .collect(Collectors.toMap(DefaultLoadBalancerCache::getName, cache -> cache)));
    }
​
    public DefaultLoadBalancerCacheManager(LoadBalancerCacheProperties loadBalancerCacheProperties) {
        this(loadBalancerCacheProperties, SERVICE_INSTANCE_CACHE_NAME);
    }
​
    private Set<DefaultLoadBalancerCache> createCaches(String[] cacheNames,
            LoadBalancerCacheProperties loadBalancerCacheProperties) {
        return Arrays.stream(cacheNames).distinct()
                .map(name -> new DefaultLoadBalancerCache(name,
                        new ConcurrentHashMapWithTimedEviction<>(loadBalancerCacheProperties.getCapacity(),
                                new DelayedTaskEvictionScheduler<>(aScheduledDaemonThreadExecutor())),
                        loadBalancerCacheProperties.getTtl().toMillis(), false))
                .collect(Collectors.toSet());
    }
​
    private ScheduledExecutorService aScheduledDaemonThreadExecutor() {
        return Executors.newSingleThreadScheduledExecutor(runnable -> {
            Thread thread = Executors.defaultThreadFactory().newThread(runnable);
            thread.setDaemon(true);
            return thread;
        });
    }
​
    @Override
    @Nullable
    public Cache getCache(String name) {
        return cacheMap.get(name);
    }
​
    @Override
    public Collection<String> getCacheNames() {
        return Collections.unmodifiableSet(cacheMap.keySet());
    }
​
}
​

Se puede ver que la lista de caché de almacenamiento se implementa a través de cacheMapeste objeto, por lo que si borramos el mapa de caché, podemos lograr el efecto de modificar la lista de servicios de caché en tiempo real.Podemos obtener su mapa de caché a través de la reflexión para una operación clara.

Implementación del código principal

        @Override
        public void onEvent(Event event) {
            try {
                if (event instanceof NamingEvent){
                    nacosWeightRandomLoadBanlancer = (NacosWeightRandomLoadBanlancer) applicationContext.getBean(ReactorLoadBalancer.class);
                    LoadBalancerCacheManager loadBalancerCacheManager = applicationContext.getBean(LoadBalancerCacheManager.class);
                    log.info("bean:{}",loadBalancerCacheManager);
                    ConcurrentMap<String, Cache> cacheMap = (ConcurrentMap<String, Cache>) ReflectUtil.getFieldValue(loadBalancerCacheManager, "cacheMap");
                    for (Map.Entry<String, Cache> stringCacheEntry : cacheMap.entrySet()) {
                        String key = stringCacheEntry.getKey();
                        Cache cache = stringCacheEntry.getValue();
                        log.info("key:{}\tvalue:{}",key,cache);
                        cache.clear();
                    }
                }
            } catch (Exception e) {
                log.error("e:{}",e);
                e.printStackTrace();
            }
        }
    }

Al implementar la interfaz de transformación del servicio de monitoreo de Nacos, se borra la lista de servicios de caché para realizar la transformación del monitoreo del servicio en tiempo real en línea y fuera de línea.

Optimización de extracción

para ser escrito

Supongo que te gusta

Origin juejin.im/post/7116743190681485349
Recomendado
Clasificación