forked from rongchao/epmet-cloud-rizhao
155 changed files with 6675 additions and 153 deletions
@ -0,0 +1,161 @@ |
|||||
|
package com.epmet.config; |
||||
|
|
||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties; |
||||
|
import com.alibaba.nacos.api.exception.NacosException; |
||||
|
import com.alibaba.nacos.api.naming.NamingService; |
||||
|
import com.alibaba.nacos.api.naming.listener.Event; |
||||
|
import com.alibaba.nacos.api.naming.listener.EventListener; |
||||
|
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
||||
|
import com.alibaba.nacos.api.naming.pojo.ListView; |
||||
|
import com.epmet.commons.tools.exception.ExceptionUtils; |
||||
|
import com.netflix.loadbalancer.DynamicServerListLoadBalancer; |
||||
|
import com.netflix.loadbalancer.ILoadBalancer; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.concurrent.*; |
||||
|
|
||||
|
/** |
||||
|
* @author wxz |
||||
|
* @Description Nacos服务列表刷新监听注册器 |
||||
|
* @date 2021.09.22 14:33:11 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Configuration |
||||
|
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceListChangedListening", name = "enable", havingValue = "true", matchIfMissing = false) |
||||
|
public class NacosServiceListListenerRegisterer { |
||||
|
|
||||
|
public static final String REFRESH_SERVER_LIST_METHOD_NAME = "restOfInit"; |
||||
|
// 服务列表拉取间隔:10s
|
||||
|
public static final long SERVICE_LIST_PULLING_DELAY_SECONDS = 10; |
||||
|
|
||||
|
private NamingService namingService; |
||||
|
|
||||
|
private ScheduledExecutorService executor; |
||||
|
|
||||
|
@Autowired |
||||
|
private NacosDiscoveryProperties discoveryProperties; |
||||
|
|
||||
|
@Autowired |
||||
|
private SpringClientFactory springClientFactory; |
||||
|
|
||||
|
// 监听中的服务列表
|
||||
|
private List<String> observingServers = new ArrayList<>(33); |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
namingService = discoveryProperties.namingServiceInstance(); |
||||
|
// 启动监听
|
||||
|
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() { |
||||
|
@Override |
||||
|
public Thread newThread(Runnable r) { |
||||
|
Thread thread = new Thread(r); |
||||
|
thread.setDaemon(true); |
||||
|
thread.setName("NacosServiceListWatchingRegisterer"); |
||||
|
return thread; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
|
||||
|
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS); |
||||
|
} |
||||
|
|
||||
|
public class EpmetNacosServiceListListener implements Runnable { |
||||
|
|
||||
|
@Override |
||||
|
public void run() { |
||||
|
doRefreshServerList(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param |
||||
|
* @return |
||||
|
* @description 执行刷新 |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 16:04:49 |
||||
|
*/ |
||||
|
private synchronized void doRefreshServerList() { |
||||
|
ListView<String> serviceListView = null; |
||||
|
try { |
||||
|
serviceListView = namingService.getServicesOfServer(1, 100); |
||||
|
//启动监听
|
||||
|
if (serviceListView == null || serviceListView.getCount() == 0) { |
||||
|
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务"); |
||||
|
return; |
||||
|
} |
||||
|
List<String> serviceList = serviceListView.getData(); |
||||
|
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList); |
||||
|
|
||||
|
for (String service : serviceList) { |
||||
|
try { |
||||
|
|
||||
|
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
|
||||
|
if (observingServers.contains(service)) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
namingService.subscribe(service, new EventListener() { |
||||
|
@Override |
||||
|
public void onEvent(Event event) { |
||||
|
if (event instanceof NamingEvent) { |
||||
|
NamingEvent namingEvent = (NamingEvent) event; |
||||
|
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances()); |
||||
|
doRefreshServerList(service); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 将该服务加入到监听列表中
|
||||
|
observingServers.add(service); |
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param serviceName |
||||
|
* @return |
||||
|
* @description 刷新ServerList |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 09:29:16 |
||||
|
*/ |
||||
|
private void doRefreshServerList(String serviceName) { |
||||
|
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
|
||||
|
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
|
||||
|
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
|
||||
|
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
|
||||
|
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
|
||||
|
// try {
|
||||
|
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
|
||||
|
// restOfInitMethod.setAccessible(true);
|
||||
|
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
|
||||
|
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
|
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
|
||||
|
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
|
||||
|
// }
|
||||
|
//}
|
||||
|
|
||||
|
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
|
||||
|
// 暂且 1 try
|
||||
|
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName); |
||||
|
if (loadBalancer instanceof DynamicServerListLoadBalancer) { |
||||
|
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer; |
||||
|
dslb.updateListOfServers(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,161 @@ |
|||||
|
package com.epmet.config; |
||||
|
|
||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties; |
||||
|
import com.alibaba.nacos.api.exception.NacosException; |
||||
|
import com.alibaba.nacos.api.naming.NamingService; |
||||
|
import com.alibaba.nacos.api.naming.listener.Event; |
||||
|
import com.alibaba.nacos.api.naming.listener.EventListener; |
||||
|
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
||||
|
import com.alibaba.nacos.api.naming.pojo.ListView; |
||||
|
import com.epmet.commons.tools.exception.ExceptionUtils; |
||||
|
import com.netflix.loadbalancer.DynamicServerListLoadBalancer; |
||||
|
import com.netflix.loadbalancer.ILoadBalancer; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.concurrent.*; |
||||
|
|
||||
|
/** |
||||
|
* @author wxz |
||||
|
* @Description Nacos服务列表刷新监听注册器 |
||||
|
* @date 2021.09.22 14:33:11 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Configuration |
||||
|
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceListChangedListening", name = "enable", havingValue = "true", matchIfMissing = false) |
||||
|
public class NacosServiceListListenerRegisterer { |
||||
|
|
||||
|
public static final String REFRESH_SERVER_LIST_METHOD_NAME = "restOfInit"; |
||||
|
// 服务列表拉取间隔:10s
|
||||
|
public static final long SERVICE_LIST_PULLING_DELAY_SECONDS = 10; |
||||
|
|
||||
|
private NamingService namingService; |
||||
|
|
||||
|
private ScheduledExecutorService executor; |
||||
|
|
||||
|
@Autowired |
||||
|
private NacosDiscoveryProperties discoveryProperties; |
||||
|
|
||||
|
@Autowired |
||||
|
private SpringClientFactory springClientFactory; |
||||
|
|
||||
|
// 监听中的服务列表
|
||||
|
private List<String> observingServers = new ArrayList<>(33); |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
namingService = discoveryProperties.namingServiceInstance(); |
||||
|
// 启动监听
|
||||
|
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() { |
||||
|
@Override |
||||
|
public Thread newThread(Runnable r) { |
||||
|
Thread thread = new Thread(r); |
||||
|
thread.setDaemon(true); |
||||
|
thread.setName("NacosServiceListWatchingRegisterer"); |
||||
|
return thread; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
|
||||
|
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS); |
||||
|
} |
||||
|
|
||||
|
public class EpmetNacosServiceListListener implements Runnable { |
||||
|
|
||||
|
@Override |
||||
|
public void run() { |
||||
|
doRefreshServerList(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param |
||||
|
* @return |
||||
|
* @description 执行刷新 |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 16:04:49 |
||||
|
*/ |
||||
|
private synchronized void doRefreshServerList() { |
||||
|
ListView<String> serviceListView = null; |
||||
|
try { |
||||
|
serviceListView = namingService.getServicesOfServer(1, 100); |
||||
|
//启动监听
|
||||
|
if (serviceListView == null || serviceListView.getCount() == 0) { |
||||
|
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务"); |
||||
|
return; |
||||
|
} |
||||
|
List<String> serviceList = serviceListView.getData(); |
||||
|
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList); |
||||
|
|
||||
|
for (String service : serviceList) { |
||||
|
try { |
||||
|
|
||||
|
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
|
||||
|
if (observingServers.contains(service)) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
namingService.subscribe(service, new EventListener() { |
||||
|
@Override |
||||
|
public void onEvent(Event event) { |
||||
|
if (event instanceof NamingEvent) { |
||||
|
NamingEvent namingEvent = (NamingEvent) event; |
||||
|
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances()); |
||||
|
doRefreshServerList(service); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 将该服务加入到监听列表中
|
||||
|
observingServers.add(service); |
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param serviceName |
||||
|
* @return |
||||
|
* @description 刷新ServerList |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 09:29:16 |
||||
|
*/ |
||||
|
private void doRefreshServerList(String serviceName) { |
||||
|
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
|
||||
|
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
|
||||
|
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
|
||||
|
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
|
||||
|
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
|
||||
|
// try {
|
||||
|
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
|
||||
|
// restOfInitMethod.setAccessible(true);
|
||||
|
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
|
||||
|
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
|
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
|
||||
|
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
|
||||
|
// }
|
||||
|
//}
|
||||
|
|
||||
|
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
|
||||
|
// 暂且 1 try
|
||||
|
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName); |
||||
|
if (loadBalancer instanceof DynamicServerListLoadBalancer) { |
||||
|
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer; |
||||
|
dslb.updateListOfServers(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,161 @@ |
|||||
|
package com.epmet.config; |
||||
|
|
||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties; |
||||
|
import com.alibaba.nacos.api.exception.NacosException; |
||||
|
import com.alibaba.nacos.api.naming.NamingService; |
||||
|
import com.alibaba.nacos.api.naming.listener.Event; |
||||
|
import com.alibaba.nacos.api.naming.listener.EventListener; |
||||
|
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
||||
|
import com.alibaba.nacos.api.naming.pojo.ListView; |
||||
|
import com.epmet.commons.tools.exception.ExceptionUtils; |
||||
|
import com.netflix.loadbalancer.DynamicServerListLoadBalancer; |
||||
|
import com.netflix.loadbalancer.ILoadBalancer; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.concurrent.*; |
||||
|
|
||||
|
/** |
||||
|
* @author wxz |
||||
|
* @Description Nacos服务列表刷新监听注册器 |
||||
|
* @date 2021.09.22 14:33:11 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Configuration |
||||
|
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceListChangedListening", name = "enable", havingValue = "true", matchIfMissing = false) |
||||
|
public class NacosServiceListListenerRegisterer { |
||||
|
|
||||
|
public static final String REFRESH_SERVER_LIST_METHOD_NAME = "restOfInit"; |
||||
|
// 服务列表拉取间隔:10s
|
||||
|
public static final long SERVICE_LIST_PULLING_DELAY_SECONDS = 10; |
||||
|
|
||||
|
private NamingService namingService; |
||||
|
|
||||
|
private ScheduledExecutorService executor; |
||||
|
|
||||
|
@Autowired |
||||
|
private NacosDiscoveryProperties discoveryProperties; |
||||
|
|
||||
|
@Autowired |
||||
|
private SpringClientFactory springClientFactory; |
||||
|
|
||||
|
// 监听中的服务列表
|
||||
|
private List<String> observingServers = new ArrayList<>(33); |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
namingService = discoveryProperties.namingServiceInstance(); |
||||
|
// 启动监听
|
||||
|
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() { |
||||
|
@Override |
||||
|
public Thread newThread(Runnable r) { |
||||
|
Thread thread = new Thread(r); |
||||
|
thread.setDaemon(true); |
||||
|
thread.setName("NacosServiceListWatchingRegisterer"); |
||||
|
return thread; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
|
||||
|
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS); |
||||
|
} |
||||
|
|
||||
|
public class EpmetNacosServiceListListener implements Runnable { |
||||
|
|
||||
|
@Override |
||||
|
public void run() { |
||||
|
doRefreshServerList(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param |
||||
|
* @return |
||||
|
* @description 执行刷新 |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 16:04:49 |
||||
|
*/ |
||||
|
private synchronized void doRefreshServerList() { |
||||
|
ListView<String> serviceListView = null; |
||||
|
try { |
||||
|
serviceListView = namingService.getServicesOfServer(1, 100); |
||||
|
//启动监听
|
||||
|
if (serviceListView == null || serviceListView.getCount() == 0) { |
||||
|
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务"); |
||||
|
return; |
||||
|
} |
||||
|
List<String> serviceList = serviceListView.getData(); |
||||
|
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList); |
||||
|
|
||||
|
for (String service : serviceList) { |
||||
|
try { |
||||
|
|
||||
|
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
|
||||
|
if (observingServers.contains(service)) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
namingService.subscribe(service, new EventListener() { |
||||
|
@Override |
||||
|
public void onEvent(Event event) { |
||||
|
if (event instanceof NamingEvent) { |
||||
|
NamingEvent namingEvent = (NamingEvent) event; |
||||
|
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances()); |
||||
|
doRefreshServerList(service); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 将该服务加入到监听列表中
|
||||
|
observingServers.add(service); |
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param serviceName |
||||
|
* @return |
||||
|
* @description 刷新ServerList |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 09:29:16 |
||||
|
*/ |
||||
|
private void doRefreshServerList(String serviceName) { |
||||
|
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
|
||||
|
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
|
||||
|
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
|
||||
|
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
|
||||
|
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
|
||||
|
// try {
|
||||
|
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
|
||||
|
// restOfInitMethod.setAccessible(true);
|
||||
|
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
|
||||
|
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
|
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
|
||||
|
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
|
||||
|
// }
|
||||
|
//}
|
||||
|
|
||||
|
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
|
||||
|
// 暂且 1 try
|
||||
|
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName); |
||||
|
if (loadBalancer instanceof DynamicServerListLoadBalancer) { |
||||
|
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer; |
||||
|
dslb.updateListOfServers(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
package com.epmet.dataaggre.constant; |
||||
|
|
||||
|
/** |
||||
|
* @Author zxc |
||||
|
* @DateTime 2021/9/23 4:06 下午 |
||||
|
* @DESC |
||||
|
*/ |
||||
|
public interface TDuckConstant { |
||||
|
|
||||
|
String CLIENT_GOV = "gov"; |
||||
|
String CLIENT_RESI = "resi"; |
||||
|
|
||||
|
String ORG_TYPE_AGENCY = "agency"; |
||||
|
String ORG_TYPE_GRID = "grid"; |
||||
|
String ORG_TYPE_DEPT = "dept"; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
package com.epmet.dataaggre.dto.epmettduck.result; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
|
||||
|
@Data |
||||
|
public class PermissionValidateResultDTO { |
||||
|
private Boolean permitted; |
||||
|
private String accessKey; |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
package com.epmet.dataaggre.dto.epmettduck.result; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
|
||||
|
/** |
||||
|
* @Description |
||||
|
* @Author zhaoqifeng |
||||
|
* @Date 2021/9/23 10:03 |
||||
|
*/ |
||||
|
@Data |
||||
|
public class RedPointResultDTO implements Serializable { |
||||
|
private static final long serialVersionUID = -2230123089546481389L; |
||||
|
/** |
||||
|
* redPoint |
||||
|
*/ |
||||
|
private String redPoint; |
||||
|
} |
||||
@ -0,0 +1,161 @@ |
|||||
|
package com.epmet.dataaggre.config; |
||||
|
|
||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties; |
||||
|
import com.alibaba.nacos.api.exception.NacosException; |
||||
|
import com.alibaba.nacos.api.naming.NamingService; |
||||
|
import com.alibaba.nacos.api.naming.listener.Event; |
||||
|
import com.alibaba.nacos.api.naming.listener.EventListener; |
||||
|
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
||||
|
import com.alibaba.nacos.api.naming.pojo.ListView; |
||||
|
import com.epmet.commons.tools.exception.ExceptionUtils; |
||||
|
import com.netflix.loadbalancer.DynamicServerListLoadBalancer; |
||||
|
import com.netflix.loadbalancer.ILoadBalancer; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.concurrent.*; |
||||
|
|
||||
|
/** |
||||
|
* @author wxz |
||||
|
* @Description Nacos服务列表刷新监听注册器 |
||||
|
* @date 2021.09.22 14:33:11 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Configuration |
||||
|
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceListChangedListening", name = "enable", havingValue = "true", matchIfMissing = false) |
||||
|
public class NacosServiceListListenerRegisterer { |
||||
|
|
||||
|
public static final String REFRESH_SERVER_LIST_METHOD_NAME = "restOfInit"; |
||||
|
// 服务列表拉取间隔:10s
|
||||
|
public static final long SERVICE_LIST_PULLING_DELAY_SECONDS = 10; |
||||
|
|
||||
|
private NamingService namingService; |
||||
|
|
||||
|
private ScheduledExecutorService executor; |
||||
|
|
||||
|
@Autowired |
||||
|
private NacosDiscoveryProperties discoveryProperties; |
||||
|
|
||||
|
@Autowired |
||||
|
private SpringClientFactory springClientFactory; |
||||
|
|
||||
|
// 监听中的服务列表
|
||||
|
private List<String> observingServers = new ArrayList<>(33); |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
namingService = discoveryProperties.namingServiceInstance(); |
||||
|
// 启动监听
|
||||
|
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() { |
||||
|
@Override |
||||
|
public Thread newThread(Runnable r) { |
||||
|
Thread thread = new Thread(r); |
||||
|
thread.setDaemon(true); |
||||
|
thread.setName("NacosServiceListWatchingRegisterer"); |
||||
|
return thread; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
|
||||
|
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS); |
||||
|
} |
||||
|
|
||||
|
public class EpmetNacosServiceListListener implements Runnable { |
||||
|
|
||||
|
@Override |
||||
|
public void run() { |
||||
|
doRefreshServerList(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param |
||||
|
* @return |
||||
|
* @description 执行刷新 |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 16:04:49 |
||||
|
*/ |
||||
|
private synchronized void doRefreshServerList() { |
||||
|
ListView<String> serviceListView = null; |
||||
|
try { |
||||
|
serviceListView = namingService.getServicesOfServer(1, 100); |
||||
|
//启动监听
|
||||
|
if (serviceListView == null || serviceListView.getCount() == 0) { |
||||
|
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务"); |
||||
|
return; |
||||
|
} |
||||
|
List<String> serviceList = serviceListView.getData(); |
||||
|
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList); |
||||
|
|
||||
|
for (String service : serviceList) { |
||||
|
try { |
||||
|
|
||||
|
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
|
||||
|
if (observingServers.contains(service)) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
namingService.subscribe(service, new EventListener() { |
||||
|
@Override |
||||
|
public void onEvent(Event event) { |
||||
|
if (event instanceof NamingEvent) { |
||||
|
NamingEvent namingEvent = (NamingEvent) event; |
||||
|
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances()); |
||||
|
doRefreshServerList(service); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 将该服务加入到监听列表中
|
||||
|
observingServers.add(service); |
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param serviceName |
||||
|
* @return |
||||
|
* @description 刷新ServerList |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 09:29:16 |
||||
|
*/ |
||||
|
private void doRefreshServerList(String serviceName) { |
||||
|
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
|
||||
|
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
|
||||
|
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
|
||||
|
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
|
||||
|
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
|
||||
|
// try {
|
||||
|
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
|
||||
|
// restOfInitMethod.setAccessible(true);
|
||||
|
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
|
||||
|
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
|
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
|
||||
|
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
|
||||
|
// }
|
||||
|
//}
|
||||
|
|
||||
|
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
|
||||
|
// 暂且 1 try
|
||||
|
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName); |
||||
|
if (loadBalancer instanceof DynamicServerListLoadBalancer) { |
||||
|
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer; |
||||
|
dslb.updateListOfServers(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
package com.epmet.dataaggre.service; |
||||
|
|
||||
|
import com.epmet.dataaggre.dto.epmettduck.result.PermissionValidateResultDTO; |
||||
|
|
||||
|
public interface QuestionnaireService { |
||||
|
PermissionValidateResultDTO resiPermissionValidate(String projectKey, String userId, String gridId); |
||||
|
|
||||
|
PermissionValidateResultDTO govPermissionValidate(String projectKey, String staffId, String customerId); |
||||
|
} |
||||
@ -0,0 +1,193 @@ |
|||||
|
package com.epmet.dataaggre.service.impl; |
||||
|
|
||||
|
import com.epmet.commons.tools.constant.AppClientConstant; |
||||
|
import com.epmet.commons.tools.constant.ServiceConstant; |
||||
|
import com.epmet.commons.tools.dto.form.IdAndNameDTO; |
||||
|
import com.epmet.commons.tools.dto.result.CustomerStaffInfoCacheResult; |
||||
|
import com.epmet.commons.tools.exception.EpmetErrorCode; |
||||
|
import com.epmet.commons.tools.exception.RenException; |
||||
|
import com.epmet.commons.tools.feign.ResultDataResolver; |
||||
|
import com.epmet.commons.tools.redis.RedisKeys; |
||||
|
import com.epmet.commons.tools.redis.RedisUtils; |
||||
|
import com.epmet.commons.tools.redis.common.CustomerStaffRedis; |
||||
|
import com.epmet.commons.tools.utils.Result; |
||||
|
import com.epmet.dataaggre.dto.epmettduck.result.PermissionValidateResultDTO; |
||||
|
import com.epmet.dataaggre.entity.epmettduck.PrPublishRangeEntity; |
||||
|
import com.epmet.dataaggre.entity.epmettduck.PrUserProjectEntity; |
||||
|
import com.epmet.dataaggre.service.QuestionnaireService; |
||||
|
import com.epmet.dataaggre.service.epmettduck.PrPublishRangeService; |
||||
|
import com.epmet.dataaggre.service.epmettduck.PrUserProjectService; |
||||
|
import com.epmet.dto.CustomerGridDTO; |
||||
|
import com.epmet.dto.form.CustomerGridFormDTO; |
||||
|
import com.epmet.feign.GovOrgOpenFeignClient; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.apache.commons.lang3.StringUtils; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.UUID; |
||||
|
|
||||
|
@Service |
||||
|
@Slf4j |
||||
|
public class QuestionnaireServiceImpl implements QuestionnaireService, ResultDataResolver { |
||||
|
|
||||
|
/** 调查问卷有效期 15min */ |
||||
|
public static final long QUESTIONNAIRE_EXPIRE_SECONDS = 15 * 60; |
||||
|
|
||||
|
@Autowired |
||||
|
private PrUserProjectService prUserProjectService; |
||||
|
|
||||
|
@Autowired |
||||
|
private PrPublishRangeService prPublishRangeService; |
||||
|
|
||||
|
@Autowired |
||||
|
private GovOrgOpenFeignClient govOrgOpenFeignClient; |
||||
|
|
||||
|
@Autowired |
||||
|
private RedisUtils redisUtils; |
||||
|
|
||||
|
@Autowired |
||||
|
private CustomerStaffRedis customerStaffRedis; |
||||
|
|
||||
|
/** |
||||
|
* @description 居民端调查问卷权限校验 |
||||
|
* |
||||
|
* @param projectKey |
||||
|
* @param userId |
||||
|
* @param gridId |
||||
|
* @return |
||||
|
* @author wxz |
||||
|
* @date 2021.09.23 17:45:25 |
||||
|
*/ |
||||
|
public PermissionValidateResultDTO resiPermissionValidate(String projectKey, String userId, String gridId) { |
||||
|
|
||||
|
PrUserProjectEntity project = prUserProjectService.getProjectEntityBykey(projectKey); |
||||
|
if (project == null || !AppClientConstant.APP_RESI.equals(project.getClient())) { |
||||
|
// 工作端只能看到发布到居民端的
|
||||
|
log.warn("【调查问卷】居民端无法查看发布到工作端的调查问卷,staffId:{}, projectKey:{}", userId, projectKey); |
||||
|
return generateValidateResult(userId, projectKey, false); |
||||
|
} |
||||
|
|
||||
|
CustomerGridFormDTO form = new CustomerGridFormDTO(); |
||||
|
form.setGridId(gridId); |
||||
|
Result<CustomerGridDTO> gridInfoResult = govOrgOpenFeignClient.getGridBaseInfoByGridId(form); |
||||
|
CustomerGridDTO gridInfo = getResultDataOrThrowsException(gridInfoResult, ServiceConstant.GOV_ORG_SERVER, EpmetErrorCode.SERVER_ERROR.getCode(), "【调查问卷】校验访问权限,查询网格信息失败"); |
||||
|
// 网格父级ID列表:网格ID(拼接起来,冒号分割)
|
||||
|
String gridIdPath = gridInfo.getPids().concat(":").concat(gridInfo.getId()); |
||||
|
List<PrPublishRangeEntity> publishRangeEntity = prPublishRangeService.getPublishRangeEntity(projectKey); |
||||
|
PermissionValidateResultDTO r = new PermissionValidateResultDTO(); |
||||
|
for (PrPublishRangeEntity rangeEntity : publishRangeEntity) { |
||||
|
if (gridIdPath.contains(rangeEntity.getOrgIds())) { |
||||
|
return generateValidateResult(userId, projectKey, true); |
||||
|
} |
||||
|
} |
||||
|
r.setPermitted(false); |
||||
|
return r; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public PermissionValidateResultDTO govPermissionValidate(String projectKey, String staffId, String customerId) { |
||||
|
PrUserProjectEntity project = prUserProjectService.getProjectEntityBykey(projectKey); |
||||
|
if (project == null || !"gov".equals(project.getClient())) { |
||||
|
// 工作端只能看到发布到工作端的
|
||||
|
log.warn("【调查问卷】工作端无法查看发布到居民端的调查问卷,staffId:{}, projectKey:{}", staffId, projectKey); |
||||
|
return generateValidateResult(staffId, projectKey, false); |
||||
|
} |
||||
|
|
||||
|
List<String> gridRangeOrgIds = new ArrayList<>(); |
||||
|
List<String> agencyRangeOrgIds = new ArrayList<>(); |
||||
|
List<String> deptRangeOrgIds = new ArrayList<>(); |
||||
|
|
||||
|
// 将发布范围分别放到3个不同的列表中
|
||||
|
List<PrPublishRangeEntity> publishRangeEntitys = prPublishRangeService.getPublishRangeEntity(projectKey); |
||||
|
publishRangeEntitys.forEach(rangeEntity -> { |
||||
|
if ("grid".equals(rangeEntity.getOrgType())) { |
||||
|
gridRangeOrgIds.add(rangeEntity.getOrgIds()); |
||||
|
} else if ("agency".equals(rangeEntity.getOrgType())) { |
||||
|
agencyRangeOrgIds.add(rangeEntity.getOrgIds()); |
||||
|
} else if ("dept".equals(rangeEntity.getOrgType())) { |
||||
|
deptRangeOrgIds.add(rangeEntity.getOrgIds()); |
||||
|
} else { |
||||
|
throw new RenException(EpmetErrorCode.SERVER_ERROR.getCode(), String.format("【调查问卷】未知的发布范围类型:%s", rangeEntity.getOrgType())); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
CustomerStaffInfoCacheResult staffInfo = customerStaffRedis.getStaffInfo(customerId, staffId); |
||||
|
PermissionValidateResultDTO r = null; |
||||
|
//if ("agency".equals(staffInfo.getFromOrgType())) {
|
||||
|
// // 来自agency
|
||||
|
//
|
||||
|
//} else if ("grid".equals(staffInfo.getFromOrgType())) {
|
||||
|
// List<IdAndNameDTO> belongGridList = staffInfo.getGridList();
|
||||
|
//
|
||||
|
//} else if ("dept".equals(staffInfo.getFromOrgType())) {
|
||||
|
//
|
||||
|
//}
|
||||
|
|
||||
|
String agencyId = staffInfo.getAgencyId(); |
||||
|
String agencyPIds = staffInfo.getAgencyPIds(); |
||||
|
|
||||
|
// 网格范围内的权限判断
|
||||
|
List<IdAndNameDTO> staffGridList = staffInfo.getGridList(); |
||||
|
for (IdAndNameDTO gridIdAndName : staffGridList) { |
||||
|
// 工作人员所属的 父orgId路径:网格id
|
||||
|
String staffGridIdPath = (StringUtils.isEmpty(agencyPIds) ? "" : agencyPIds.concat(":")).concat(agencyId).concat(":").concat(gridIdAndName.getId()); |
||||
|
for (String gridRangeOrgId : gridRangeOrgIds) { |
||||
|
if (staffGridIdPath.contains(gridRangeOrgId)) { |
||||
|
r = generateValidateResult(staffId, projectKey, true); |
||||
|
return r; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// dept范围内的权限判断
|
||||
|
List<IdAndNameDTO> staffDeptList = staffInfo.getDeptList(); |
||||
|
for (IdAndNameDTO deptIdAndName : staffDeptList) { |
||||
|
// 工作人员所属的 父orgId路径:网格id
|
||||
|
String staffDeptIdPath = (StringUtils.isEmpty(agencyPIds) ? "" : agencyPIds.concat(":")).concat(agencyId).concat(":").concat(deptIdAndName.getId()); |
||||
|
for (String deptRangeOrgIdPath : deptRangeOrgIds) { |
||||
|
if (staffDeptIdPath.contains(deptRangeOrgIdPath)) { |
||||
|
r = generateValidateResult(staffId, projectKey, true); |
||||
|
return r; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// agency范围内的权限判断
|
||||
|
String staffAgencyIdPath = (StringUtils.isEmpty(agencyPIds) ? "" : agencyPIds.concat(":")).concat(agencyId); |
||||
|
for (String agencyRangeOrgId : agencyRangeOrgIds) { |
||||
|
if (staffAgencyIdPath.contains(agencyRangeOrgId)) { |
||||
|
r = generateValidateResult(staffId, projectKey, true); |
||||
|
return r; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 如果上述范围中都不能判断通过,那么返回一个不通过的结果给到前端
|
||||
|
r = generateValidateResult(staffId, projectKey, false); |
||||
|
return r; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description 生成权限允许的返回结果 |
||||
|
* |
||||
|
* @param userId |
||||
|
* @param projectKey |
||||
|
* @param permitted 是否允许访问 |
||||
|
* @return |
||||
|
* @author wxz |
||||
|
* @date 2021.09.23 23:19:17 |
||||
|
*/ |
||||
|
private PermissionValidateResultDTO generateValidateResult(String userId, String projectKey, Boolean permitted) { |
||||
|
PermissionValidateResultDTO d = new PermissionValidateResultDTO(); |
||||
|
d.setPermitted(permitted); |
||||
|
if (permitted) { |
||||
|
String accessKey = UUID.randomUUID().toString().replace("-", ""); |
||||
|
redisUtils.set(RedisKeys.getQuestionnaireAccessKey(userId, projectKey), accessKey, QUESTIONNAIRE_EXPIRE_SECONDS); |
||||
|
d.setAccessKey(accessKey); |
||||
|
} |
||||
|
return d; |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,161 @@ |
|||||
|
package com.epmet.datareport.config; |
||||
|
|
||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties; |
||||
|
import com.alibaba.nacos.api.exception.NacosException; |
||||
|
import com.alibaba.nacos.api.naming.NamingService; |
||||
|
import com.alibaba.nacos.api.naming.listener.Event; |
||||
|
import com.alibaba.nacos.api.naming.listener.EventListener; |
||||
|
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
||||
|
import com.alibaba.nacos.api.naming.pojo.ListView; |
||||
|
import com.epmet.commons.tools.exception.ExceptionUtils; |
||||
|
import com.netflix.loadbalancer.DynamicServerListLoadBalancer; |
||||
|
import com.netflix.loadbalancer.ILoadBalancer; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.concurrent.*; |
||||
|
|
||||
|
/** |
||||
|
* @author wxz |
||||
|
* @Description Nacos服务列表刷新监听注册器 |
||||
|
* @date 2021.09.22 14:33:11 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Configuration |
||||
|
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceListChangedListening", name = "enable", havingValue = "true", matchIfMissing = false) |
||||
|
public class NacosServiceListListenerRegisterer { |
||||
|
|
||||
|
public static final String REFRESH_SERVER_LIST_METHOD_NAME = "restOfInit"; |
||||
|
// 服务列表拉取间隔:10s
|
||||
|
public static final long SERVICE_LIST_PULLING_DELAY_SECONDS = 10; |
||||
|
|
||||
|
private NamingService namingService; |
||||
|
|
||||
|
private ScheduledExecutorService executor; |
||||
|
|
||||
|
@Autowired |
||||
|
private NacosDiscoveryProperties discoveryProperties; |
||||
|
|
||||
|
@Autowired |
||||
|
private SpringClientFactory springClientFactory; |
||||
|
|
||||
|
// 监听中的服务列表
|
||||
|
private List<String> observingServers = new ArrayList<>(33); |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
namingService = discoveryProperties.namingServiceInstance(); |
||||
|
// 启动监听
|
||||
|
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() { |
||||
|
@Override |
||||
|
public Thread newThread(Runnable r) { |
||||
|
Thread thread = new Thread(r); |
||||
|
thread.setDaemon(true); |
||||
|
thread.setName("NacosServiceListWatchingRegisterer"); |
||||
|
return thread; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
|
||||
|
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS); |
||||
|
} |
||||
|
|
||||
|
public class EpmetNacosServiceListListener implements Runnable { |
||||
|
|
||||
|
@Override |
||||
|
public void run() { |
||||
|
doRefreshServerList(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param |
||||
|
* @return |
||||
|
* @description 执行刷新 |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 16:04:49 |
||||
|
*/ |
||||
|
private synchronized void doRefreshServerList() { |
||||
|
ListView<String> serviceListView = null; |
||||
|
try { |
||||
|
serviceListView = namingService.getServicesOfServer(1, 100); |
||||
|
//启动监听
|
||||
|
if (serviceListView == null || serviceListView.getCount() == 0) { |
||||
|
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务"); |
||||
|
return; |
||||
|
} |
||||
|
List<String> serviceList = serviceListView.getData(); |
||||
|
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList); |
||||
|
|
||||
|
for (String service : serviceList) { |
||||
|
try { |
||||
|
|
||||
|
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
|
||||
|
if (observingServers.contains(service)) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
namingService.subscribe(service, new EventListener() { |
||||
|
@Override |
||||
|
public void onEvent(Event event) { |
||||
|
if (event instanceof NamingEvent) { |
||||
|
NamingEvent namingEvent = (NamingEvent) event; |
||||
|
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances()); |
||||
|
doRefreshServerList(service); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 将该服务加入到监听列表中
|
||||
|
observingServers.add(service); |
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param serviceName |
||||
|
* @return |
||||
|
* @description 刷新ServerList |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 09:29:16 |
||||
|
*/ |
||||
|
private void doRefreshServerList(String serviceName) { |
||||
|
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
|
||||
|
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
|
||||
|
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
|
||||
|
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
|
||||
|
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
|
||||
|
// try {
|
||||
|
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
|
||||
|
// restOfInitMethod.setAccessible(true);
|
||||
|
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
|
||||
|
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
|
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
|
||||
|
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
|
||||
|
// }
|
||||
|
//}
|
||||
|
|
||||
|
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
|
||||
|
// 暂且 1 try
|
||||
|
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName); |
||||
|
if (loadBalancer instanceof DynamicServerListLoadBalancer) { |
||||
|
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer; |
||||
|
dslb.updateListOfServers(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,161 @@ |
|||||
|
package com.epmet.config; |
||||
|
|
||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties; |
||||
|
import com.alibaba.nacos.api.exception.NacosException; |
||||
|
import com.alibaba.nacos.api.naming.NamingService; |
||||
|
import com.alibaba.nacos.api.naming.listener.Event; |
||||
|
import com.alibaba.nacos.api.naming.listener.EventListener; |
||||
|
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
||||
|
import com.alibaba.nacos.api.naming.pojo.ListView; |
||||
|
import com.epmet.commons.tools.exception.ExceptionUtils; |
||||
|
import com.netflix.loadbalancer.DynamicServerListLoadBalancer; |
||||
|
import com.netflix.loadbalancer.ILoadBalancer; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.concurrent.*; |
||||
|
|
||||
|
/** |
||||
|
* @author wxz |
||||
|
* @Description Nacos服务列表刷新监听注册器 |
||||
|
* @date 2021.09.22 14:33:11 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Configuration |
||||
|
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceListChangedListening", name = "enable", havingValue = "true", matchIfMissing = false) |
||||
|
public class NacosServiceListListenerRegisterer { |
||||
|
|
||||
|
public static final String REFRESH_SERVER_LIST_METHOD_NAME = "restOfInit"; |
||||
|
// 服务列表拉取间隔:10s
|
||||
|
public static final long SERVICE_LIST_PULLING_DELAY_SECONDS = 10; |
||||
|
|
||||
|
private NamingService namingService; |
||||
|
|
||||
|
private ScheduledExecutorService executor; |
||||
|
|
||||
|
@Autowired |
||||
|
private NacosDiscoveryProperties discoveryProperties; |
||||
|
|
||||
|
@Autowired |
||||
|
private SpringClientFactory springClientFactory; |
||||
|
|
||||
|
// 监听中的服务列表
|
||||
|
private List<String> observingServers = new ArrayList<>(33); |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
namingService = discoveryProperties.namingServiceInstance(); |
||||
|
// 启动监听
|
||||
|
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() { |
||||
|
@Override |
||||
|
public Thread newThread(Runnable r) { |
||||
|
Thread thread = new Thread(r); |
||||
|
thread.setDaemon(true); |
||||
|
thread.setName("NacosServiceListWatchingRegisterer"); |
||||
|
return thread; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
|
||||
|
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS); |
||||
|
} |
||||
|
|
||||
|
public class EpmetNacosServiceListListener implements Runnable { |
||||
|
|
||||
|
@Override |
||||
|
public void run() { |
||||
|
doRefreshServerList(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param |
||||
|
* @return |
||||
|
* @description 执行刷新 |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 16:04:49 |
||||
|
*/ |
||||
|
private synchronized void doRefreshServerList() { |
||||
|
ListView<String> serviceListView = null; |
||||
|
try { |
||||
|
serviceListView = namingService.getServicesOfServer(1, 100); |
||||
|
//启动监听
|
||||
|
if (serviceListView == null || serviceListView.getCount() == 0) { |
||||
|
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务"); |
||||
|
return; |
||||
|
} |
||||
|
List<String> serviceList = serviceListView.getData(); |
||||
|
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList); |
||||
|
|
||||
|
for (String service : serviceList) { |
||||
|
try { |
||||
|
|
||||
|
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
|
||||
|
if (observingServers.contains(service)) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
namingService.subscribe(service, new EventListener() { |
||||
|
@Override |
||||
|
public void onEvent(Event event) { |
||||
|
if (event instanceof NamingEvent) { |
||||
|
NamingEvent namingEvent = (NamingEvent) event; |
||||
|
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances()); |
||||
|
doRefreshServerList(service); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 将该服务加入到监听列表中
|
||||
|
observingServers.add(service); |
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param serviceName |
||||
|
* @return |
||||
|
* @description 刷新ServerList |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 09:29:16 |
||||
|
*/ |
||||
|
private void doRefreshServerList(String serviceName) { |
||||
|
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
|
||||
|
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
|
||||
|
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
|
||||
|
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
|
||||
|
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
|
||||
|
// try {
|
||||
|
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
|
||||
|
// restOfInitMethod.setAccessible(true);
|
||||
|
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
|
||||
|
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
|
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
|
||||
|
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
|
||||
|
// }
|
||||
|
//}
|
||||
|
|
||||
|
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
|
||||
|
// 暂且 1 try
|
||||
|
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName); |
||||
|
if (loadBalancer instanceof DynamicServerListLoadBalancer) { |
||||
|
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer; |
||||
|
dslb.updateListOfServers(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,161 @@ |
|||||
|
package com.epmet.config; |
||||
|
|
||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties; |
||||
|
import com.alibaba.nacos.api.exception.NacosException; |
||||
|
import com.alibaba.nacos.api.naming.NamingService; |
||||
|
import com.alibaba.nacos.api.naming.listener.Event; |
||||
|
import com.alibaba.nacos.api.naming.listener.EventListener; |
||||
|
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
||||
|
import com.alibaba.nacos.api.naming.pojo.ListView; |
||||
|
import com.epmet.commons.tools.exception.ExceptionUtils; |
||||
|
import com.netflix.loadbalancer.DynamicServerListLoadBalancer; |
||||
|
import com.netflix.loadbalancer.ILoadBalancer; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.concurrent.*; |
||||
|
|
||||
|
/** |
||||
|
* @author wxz |
||||
|
* @Description Nacos服务列表刷新监听注册器 |
||||
|
* @date 2021.09.22 14:33:11 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Configuration |
||||
|
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceListChangedListening", name = "enable", havingValue = "true", matchIfMissing = false) |
||||
|
public class NacosServiceListListenerRegisterer { |
||||
|
|
||||
|
public static final String REFRESH_SERVER_LIST_METHOD_NAME = "restOfInit"; |
||||
|
// 服务列表拉取间隔:10s
|
||||
|
public static final long SERVICE_LIST_PULLING_DELAY_SECONDS = 10; |
||||
|
|
||||
|
private NamingService namingService; |
||||
|
|
||||
|
private ScheduledExecutorService executor; |
||||
|
|
||||
|
@Autowired |
||||
|
private NacosDiscoveryProperties discoveryProperties; |
||||
|
|
||||
|
@Autowired |
||||
|
private SpringClientFactory springClientFactory; |
||||
|
|
||||
|
// 监听中的服务列表
|
||||
|
private List<String> observingServers = new ArrayList<>(33); |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
namingService = discoveryProperties.namingServiceInstance(); |
||||
|
// 启动监听
|
||||
|
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() { |
||||
|
@Override |
||||
|
public Thread newThread(Runnable r) { |
||||
|
Thread thread = new Thread(r); |
||||
|
thread.setDaemon(true); |
||||
|
thread.setName("NacosServiceListWatchingRegisterer"); |
||||
|
return thread; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
|
||||
|
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS); |
||||
|
} |
||||
|
|
||||
|
public class EpmetNacosServiceListListener implements Runnable { |
||||
|
|
||||
|
@Override |
||||
|
public void run() { |
||||
|
doRefreshServerList(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param |
||||
|
* @return |
||||
|
* @description 执行刷新 |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 16:04:49 |
||||
|
*/ |
||||
|
private synchronized void doRefreshServerList() { |
||||
|
ListView<String> serviceListView = null; |
||||
|
try { |
||||
|
serviceListView = namingService.getServicesOfServer(1, 100); |
||||
|
//启动监听
|
||||
|
if (serviceListView == null || serviceListView.getCount() == 0) { |
||||
|
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务"); |
||||
|
return; |
||||
|
} |
||||
|
List<String> serviceList = serviceListView.getData(); |
||||
|
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList); |
||||
|
|
||||
|
for (String service : serviceList) { |
||||
|
try { |
||||
|
|
||||
|
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
|
||||
|
if (observingServers.contains(service)) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
namingService.subscribe(service, new EventListener() { |
||||
|
@Override |
||||
|
public void onEvent(Event event) { |
||||
|
if (event instanceof NamingEvent) { |
||||
|
NamingEvent namingEvent = (NamingEvent) event; |
||||
|
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances()); |
||||
|
doRefreshServerList(service); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 将该服务加入到监听列表中
|
||||
|
observingServers.add(service); |
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param serviceName |
||||
|
* @return |
||||
|
* @description 刷新ServerList |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 09:29:16 |
||||
|
*/ |
||||
|
private void doRefreshServerList(String serviceName) { |
||||
|
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
|
||||
|
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
|
||||
|
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
|
||||
|
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
|
||||
|
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
|
||||
|
// try {
|
||||
|
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
|
||||
|
// restOfInitMethod.setAccessible(true);
|
||||
|
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
|
||||
|
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
|
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
|
||||
|
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
|
||||
|
// }
|
||||
|
//}
|
||||
|
|
||||
|
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
|
||||
|
// 暂且 1 try
|
||||
|
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName); |
||||
|
if (loadBalancer instanceof DynamicServerListLoadBalancer) { |
||||
|
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer; |
||||
|
dslb.updateListOfServers(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,161 @@ |
|||||
|
package com.epmet.config; |
||||
|
|
||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties; |
||||
|
import com.alibaba.nacos.api.exception.NacosException; |
||||
|
import com.alibaba.nacos.api.naming.NamingService; |
||||
|
import com.alibaba.nacos.api.naming.listener.Event; |
||||
|
import com.alibaba.nacos.api.naming.listener.EventListener; |
||||
|
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
||||
|
import com.alibaba.nacos.api.naming.pojo.ListView; |
||||
|
import com.epmet.commons.tools.exception.ExceptionUtils; |
||||
|
import com.netflix.loadbalancer.DynamicServerListLoadBalancer; |
||||
|
import com.netflix.loadbalancer.ILoadBalancer; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.concurrent.*; |
||||
|
|
||||
|
/** |
||||
|
* @author wxz |
||||
|
* @Description Nacos服务列表刷新监听注册器 |
||||
|
* @date 2021.09.22 14:33:11 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Configuration |
||||
|
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceListChangedListening", name = "enable", havingValue = "true", matchIfMissing = false) |
||||
|
public class NacosServiceListListenerRegisterer { |
||||
|
|
||||
|
public static final String REFRESH_SERVER_LIST_METHOD_NAME = "restOfInit"; |
||||
|
// 服务列表拉取间隔:10s
|
||||
|
public static final long SERVICE_LIST_PULLING_DELAY_SECONDS = 10; |
||||
|
|
||||
|
private NamingService namingService; |
||||
|
|
||||
|
private ScheduledExecutorService executor; |
||||
|
|
||||
|
@Autowired |
||||
|
private NacosDiscoveryProperties discoveryProperties; |
||||
|
|
||||
|
@Autowired |
||||
|
private SpringClientFactory springClientFactory; |
||||
|
|
||||
|
// 监听中的服务列表
|
||||
|
private List<String> observingServers = new ArrayList<>(33); |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
namingService = discoveryProperties.namingServiceInstance(); |
||||
|
// 启动监听
|
||||
|
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() { |
||||
|
@Override |
||||
|
public Thread newThread(Runnable r) { |
||||
|
Thread thread = new Thread(r); |
||||
|
thread.setDaemon(true); |
||||
|
thread.setName("NacosServiceListWatchingRegisterer"); |
||||
|
return thread; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
|
||||
|
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS); |
||||
|
} |
||||
|
|
||||
|
public class EpmetNacosServiceListListener implements Runnable { |
||||
|
|
||||
|
@Override |
||||
|
public void run() { |
||||
|
doRefreshServerList(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param |
||||
|
* @return |
||||
|
* @description 执行刷新 |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 16:04:49 |
||||
|
*/ |
||||
|
private synchronized void doRefreshServerList() { |
||||
|
ListView<String> serviceListView = null; |
||||
|
try { |
||||
|
serviceListView = namingService.getServicesOfServer(1, 100); |
||||
|
//启动监听
|
||||
|
if (serviceListView == null || serviceListView.getCount() == 0) { |
||||
|
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务"); |
||||
|
return; |
||||
|
} |
||||
|
List<String> serviceList = serviceListView.getData(); |
||||
|
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList); |
||||
|
|
||||
|
for (String service : serviceList) { |
||||
|
try { |
||||
|
|
||||
|
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
|
||||
|
if (observingServers.contains(service)) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
namingService.subscribe(service, new EventListener() { |
||||
|
@Override |
||||
|
public void onEvent(Event event) { |
||||
|
if (event instanceof NamingEvent) { |
||||
|
NamingEvent namingEvent = (NamingEvent) event; |
||||
|
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances()); |
||||
|
doRefreshServerList(service); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 将该服务加入到监听列表中
|
||||
|
observingServers.add(service); |
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param serviceName |
||||
|
* @return |
||||
|
* @description 刷新ServerList |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 09:29:16 |
||||
|
*/ |
||||
|
private void doRefreshServerList(String serviceName) { |
||||
|
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
|
||||
|
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
|
||||
|
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
|
||||
|
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
|
||||
|
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
|
||||
|
// try {
|
||||
|
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
|
||||
|
// restOfInitMethod.setAccessible(true);
|
||||
|
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
|
||||
|
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
|
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
|
||||
|
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
|
||||
|
// }
|
||||
|
//}
|
||||
|
|
||||
|
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
|
||||
|
// 暂且 1 try
|
||||
|
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName); |
||||
|
if (loadBalancer instanceof DynamicServerListLoadBalancer) { |
||||
|
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer; |
||||
|
dslb.updateListOfServers(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,161 @@ |
|||||
|
package com.epmet.config; |
||||
|
|
||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties; |
||||
|
import com.alibaba.nacos.api.exception.NacosException; |
||||
|
import com.alibaba.nacos.api.naming.NamingService; |
||||
|
import com.alibaba.nacos.api.naming.listener.Event; |
||||
|
import com.alibaba.nacos.api.naming.listener.EventListener; |
||||
|
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
||||
|
import com.alibaba.nacos.api.naming.pojo.ListView; |
||||
|
import com.epmet.commons.tools.exception.ExceptionUtils; |
||||
|
import com.netflix.loadbalancer.DynamicServerListLoadBalancer; |
||||
|
import com.netflix.loadbalancer.ILoadBalancer; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.concurrent.*; |
||||
|
|
||||
|
/** |
||||
|
* @author wxz |
||||
|
* @Description Nacos服务列表刷新监听注册器 |
||||
|
* @date 2021.09.22 14:33:11 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Configuration |
||||
|
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceListChangedListening", name = "enable", havingValue = "true", matchIfMissing = false) |
||||
|
public class NacosServiceListListenerRegisterer { |
||||
|
|
||||
|
public static final String REFRESH_SERVER_LIST_METHOD_NAME = "restOfInit"; |
||||
|
// 服务列表拉取间隔:10s
|
||||
|
public static final long SERVICE_LIST_PULLING_DELAY_SECONDS = 10; |
||||
|
|
||||
|
private NamingService namingService; |
||||
|
|
||||
|
private ScheduledExecutorService executor; |
||||
|
|
||||
|
@Autowired |
||||
|
private NacosDiscoveryProperties discoveryProperties; |
||||
|
|
||||
|
@Autowired |
||||
|
private SpringClientFactory springClientFactory; |
||||
|
|
||||
|
// 监听中的服务列表
|
||||
|
private List<String> observingServers = new ArrayList<>(33); |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
namingService = discoveryProperties.namingServiceInstance(); |
||||
|
// 启动监听
|
||||
|
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() { |
||||
|
@Override |
||||
|
public Thread newThread(Runnable r) { |
||||
|
Thread thread = new Thread(r); |
||||
|
thread.setDaemon(true); |
||||
|
thread.setName("NacosServiceListWatchingRegisterer"); |
||||
|
return thread; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
|
||||
|
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS); |
||||
|
} |
||||
|
|
||||
|
public class EpmetNacosServiceListListener implements Runnable { |
||||
|
|
||||
|
@Override |
||||
|
public void run() { |
||||
|
doRefreshServerList(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param |
||||
|
* @return |
||||
|
* @description 执行刷新 |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 16:04:49 |
||||
|
*/ |
||||
|
private synchronized void doRefreshServerList() { |
||||
|
ListView<String> serviceListView = null; |
||||
|
try { |
||||
|
serviceListView = namingService.getServicesOfServer(1, 100); |
||||
|
//启动监听
|
||||
|
if (serviceListView == null || serviceListView.getCount() == 0) { |
||||
|
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务"); |
||||
|
return; |
||||
|
} |
||||
|
List<String> serviceList = serviceListView.getData(); |
||||
|
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList); |
||||
|
|
||||
|
for (String service : serviceList) { |
||||
|
try { |
||||
|
|
||||
|
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
|
||||
|
if (observingServers.contains(service)) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
namingService.subscribe(service, new EventListener() { |
||||
|
@Override |
||||
|
public void onEvent(Event event) { |
||||
|
if (event instanceof NamingEvent) { |
||||
|
NamingEvent namingEvent = (NamingEvent) event; |
||||
|
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances()); |
||||
|
doRefreshServerList(service); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 将该服务加入到监听列表中
|
||||
|
observingServers.add(service); |
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param serviceName |
||||
|
* @return |
||||
|
* @description 刷新ServerList |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 09:29:16 |
||||
|
*/ |
||||
|
private void doRefreshServerList(String serviceName) { |
||||
|
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
|
||||
|
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
|
||||
|
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
|
||||
|
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
|
||||
|
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
|
||||
|
// try {
|
||||
|
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
|
||||
|
// restOfInitMethod.setAccessible(true);
|
||||
|
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
|
||||
|
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
|
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
|
||||
|
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
|
||||
|
// }
|
||||
|
//}
|
||||
|
|
||||
|
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
|
||||
|
// 暂且 1 try
|
||||
|
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName); |
||||
|
if (loadBalancer instanceof DynamicServerListLoadBalancer) { |
||||
|
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer; |
||||
|
dslb.updateListOfServers(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,161 @@ |
|||||
|
package com.epmet.config; |
||||
|
|
||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties; |
||||
|
import com.alibaba.nacos.api.exception.NacosException; |
||||
|
import com.alibaba.nacos.api.naming.NamingService; |
||||
|
import com.alibaba.nacos.api.naming.listener.Event; |
||||
|
import com.alibaba.nacos.api.naming.listener.EventListener; |
||||
|
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
||||
|
import com.alibaba.nacos.api.naming.pojo.ListView; |
||||
|
import com.epmet.commons.tools.exception.ExceptionUtils; |
||||
|
import com.netflix.loadbalancer.DynamicServerListLoadBalancer; |
||||
|
import com.netflix.loadbalancer.ILoadBalancer; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.concurrent.*; |
||||
|
|
||||
|
/** |
||||
|
* @author wxz |
||||
|
* @Description Nacos服务列表刷新监听注册器 |
||||
|
* @date 2021.09.22 14:33:11 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Configuration |
||||
|
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceListChangedListening", name = "enable", havingValue = "true", matchIfMissing = false) |
||||
|
public class NacosServiceListListenerRegisterer { |
||||
|
|
||||
|
public static final String REFRESH_SERVER_LIST_METHOD_NAME = "restOfInit"; |
||||
|
// 服务列表拉取间隔:10s
|
||||
|
public static final long SERVICE_LIST_PULLING_DELAY_SECONDS = 10; |
||||
|
|
||||
|
private NamingService namingService; |
||||
|
|
||||
|
private ScheduledExecutorService executor; |
||||
|
|
||||
|
@Autowired |
||||
|
private NacosDiscoveryProperties discoveryProperties; |
||||
|
|
||||
|
@Autowired |
||||
|
private SpringClientFactory springClientFactory; |
||||
|
|
||||
|
// 监听中的服务列表
|
||||
|
private List<String> observingServers = new ArrayList<>(33); |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
namingService = discoveryProperties.namingServiceInstance(); |
||||
|
// 启动监听
|
||||
|
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() { |
||||
|
@Override |
||||
|
public Thread newThread(Runnable r) { |
||||
|
Thread thread = new Thread(r); |
||||
|
thread.setDaemon(true); |
||||
|
thread.setName("NacosServiceListWatchingRegisterer"); |
||||
|
return thread; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
|
||||
|
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS); |
||||
|
} |
||||
|
|
||||
|
public class EpmetNacosServiceListListener implements Runnable { |
||||
|
|
||||
|
@Override |
||||
|
public void run() { |
||||
|
doRefreshServerList(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param |
||||
|
* @return |
||||
|
* @description 执行刷新 |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 16:04:49 |
||||
|
*/ |
||||
|
private synchronized void doRefreshServerList() { |
||||
|
ListView<String> serviceListView = null; |
||||
|
try { |
||||
|
serviceListView = namingService.getServicesOfServer(1, 100); |
||||
|
//启动监听
|
||||
|
if (serviceListView == null || serviceListView.getCount() == 0) { |
||||
|
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务"); |
||||
|
return; |
||||
|
} |
||||
|
List<String> serviceList = serviceListView.getData(); |
||||
|
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList); |
||||
|
|
||||
|
for (String service : serviceList) { |
||||
|
try { |
||||
|
|
||||
|
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
|
||||
|
if (observingServers.contains(service)) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
namingService.subscribe(service, new EventListener() { |
||||
|
@Override |
||||
|
public void onEvent(Event event) { |
||||
|
if (event instanceof NamingEvent) { |
||||
|
NamingEvent namingEvent = (NamingEvent) event; |
||||
|
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances()); |
||||
|
doRefreshServerList(service); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 将该服务加入到监听列表中
|
||||
|
observingServers.add(service); |
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param serviceName |
||||
|
* @return |
||||
|
* @description 刷新ServerList |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 09:29:16 |
||||
|
*/ |
||||
|
private void doRefreshServerList(String serviceName) { |
||||
|
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
|
||||
|
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
|
||||
|
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
|
||||
|
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
|
||||
|
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
|
||||
|
// try {
|
||||
|
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
|
||||
|
// restOfInitMethod.setAccessible(true);
|
||||
|
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
|
||||
|
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
|
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
|
||||
|
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
|
||||
|
// }
|
||||
|
//}
|
||||
|
|
||||
|
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
|
||||
|
// 暂且 1 try
|
||||
|
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName); |
||||
|
if (loadBalancer instanceof DynamicServerListLoadBalancer) { |
||||
|
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer; |
||||
|
dslb.updateListOfServers(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,161 @@ |
|||||
|
package com.epmet.config; |
||||
|
|
||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties; |
||||
|
import com.alibaba.nacos.api.exception.NacosException; |
||||
|
import com.alibaba.nacos.api.naming.NamingService; |
||||
|
import com.alibaba.nacos.api.naming.listener.Event; |
||||
|
import com.alibaba.nacos.api.naming.listener.EventListener; |
||||
|
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
||||
|
import com.alibaba.nacos.api.naming.pojo.ListView; |
||||
|
import com.epmet.commons.tools.exception.ExceptionUtils; |
||||
|
import com.netflix.loadbalancer.DynamicServerListLoadBalancer; |
||||
|
import com.netflix.loadbalancer.ILoadBalancer; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.concurrent.*; |
||||
|
|
||||
|
/** |
||||
|
* @author wxz |
||||
|
* @Description Nacos服务列表刷新监听注册器 |
||||
|
* @date 2021.09.22 14:33:11 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Configuration |
||||
|
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceListChangedListening", name = "enable", havingValue = "true", matchIfMissing = false) |
||||
|
public class NacosServiceListListenerRegisterer { |
||||
|
|
||||
|
public static final String REFRESH_SERVER_LIST_METHOD_NAME = "restOfInit"; |
||||
|
// 服务列表拉取间隔:10s
|
||||
|
public static final long SERVICE_LIST_PULLING_DELAY_SECONDS = 10; |
||||
|
|
||||
|
private NamingService namingService; |
||||
|
|
||||
|
private ScheduledExecutorService executor; |
||||
|
|
||||
|
@Autowired |
||||
|
private NacosDiscoveryProperties discoveryProperties; |
||||
|
|
||||
|
@Autowired |
||||
|
private SpringClientFactory springClientFactory; |
||||
|
|
||||
|
// 监听中的服务列表
|
||||
|
private List<String> observingServers = new ArrayList<>(33); |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
namingService = discoveryProperties.namingServiceInstance(); |
||||
|
// 启动监听
|
||||
|
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() { |
||||
|
@Override |
||||
|
public Thread newThread(Runnable r) { |
||||
|
Thread thread = new Thread(r); |
||||
|
thread.setDaemon(true); |
||||
|
thread.setName("NacosServiceListWatchingRegisterer"); |
||||
|
return thread; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
|
||||
|
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS); |
||||
|
} |
||||
|
|
||||
|
public class EpmetNacosServiceListListener implements Runnable { |
||||
|
|
||||
|
@Override |
||||
|
public void run() { |
||||
|
doRefreshServerList(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param |
||||
|
* @return |
||||
|
* @description 执行刷新 |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 16:04:49 |
||||
|
*/ |
||||
|
private synchronized void doRefreshServerList() { |
||||
|
ListView<String> serviceListView = null; |
||||
|
try { |
||||
|
serviceListView = namingService.getServicesOfServer(1, 100); |
||||
|
//启动监听
|
||||
|
if (serviceListView == null || serviceListView.getCount() == 0) { |
||||
|
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务"); |
||||
|
return; |
||||
|
} |
||||
|
List<String> serviceList = serviceListView.getData(); |
||||
|
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList); |
||||
|
|
||||
|
for (String service : serviceList) { |
||||
|
try { |
||||
|
|
||||
|
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
|
||||
|
if (observingServers.contains(service)) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
namingService.subscribe(service, new EventListener() { |
||||
|
@Override |
||||
|
public void onEvent(Event event) { |
||||
|
if (event instanceof NamingEvent) { |
||||
|
NamingEvent namingEvent = (NamingEvent) event; |
||||
|
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances()); |
||||
|
doRefreshServerList(service); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 将该服务加入到监听列表中
|
||||
|
observingServers.add(service); |
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param serviceName |
||||
|
* @return |
||||
|
* @description 刷新ServerList |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 09:29:16 |
||||
|
*/ |
||||
|
private void doRefreshServerList(String serviceName) { |
||||
|
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
|
||||
|
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
|
||||
|
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
|
||||
|
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
|
||||
|
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
|
||||
|
// try {
|
||||
|
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
|
||||
|
// restOfInitMethod.setAccessible(true);
|
||||
|
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
|
||||
|
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
|
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
|
||||
|
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
|
||||
|
// }
|
||||
|
//}
|
||||
|
|
||||
|
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
|
||||
|
// 暂且 1 try
|
||||
|
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName); |
||||
|
if (loadBalancer instanceof DynamicServerListLoadBalancer) { |
||||
|
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer; |
||||
|
dslb.updateListOfServers(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,161 @@ |
|||||
|
package com.epmet.config; |
||||
|
|
||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties; |
||||
|
import com.alibaba.nacos.api.exception.NacosException; |
||||
|
import com.alibaba.nacos.api.naming.NamingService; |
||||
|
import com.alibaba.nacos.api.naming.listener.Event; |
||||
|
import com.alibaba.nacos.api.naming.listener.EventListener; |
||||
|
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
||||
|
import com.alibaba.nacos.api.naming.pojo.ListView; |
||||
|
import com.epmet.commons.tools.exception.ExceptionUtils; |
||||
|
import com.netflix.loadbalancer.DynamicServerListLoadBalancer; |
||||
|
import com.netflix.loadbalancer.ILoadBalancer; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.concurrent.*; |
||||
|
|
||||
|
/** |
||||
|
* @author wxz |
||||
|
* @Description Nacos服务列表刷新监听注册器 |
||||
|
* @date 2021.09.22 14:33:11 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Configuration |
||||
|
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceListChangedListening", name = "enable", havingValue = "true", matchIfMissing = false) |
||||
|
public class NacosServiceListListenerRegisterer { |
||||
|
|
||||
|
public static final String REFRESH_SERVER_LIST_METHOD_NAME = "restOfInit"; |
||||
|
// 服务列表拉取间隔:10s
|
||||
|
public static final long SERVICE_LIST_PULLING_DELAY_SECONDS = 10; |
||||
|
|
||||
|
private NamingService namingService; |
||||
|
|
||||
|
private ScheduledExecutorService executor; |
||||
|
|
||||
|
@Autowired |
||||
|
private NacosDiscoveryProperties discoveryProperties; |
||||
|
|
||||
|
@Autowired |
||||
|
private SpringClientFactory springClientFactory; |
||||
|
|
||||
|
// 监听中的服务列表
|
||||
|
private List<String> observingServers = new ArrayList<>(33); |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
namingService = discoveryProperties.namingServiceInstance(); |
||||
|
// 启动监听
|
||||
|
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() { |
||||
|
@Override |
||||
|
public Thread newThread(Runnable r) { |
||||
|
Thread thread = new Thread(r); |
||||
|
thread.setDaemon(true); |
||||
|
thread.setName("NacosServiceListWatchingRegisterer"); |
||||
|
return thread; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
|
||||
|
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS); |
||||
|
} |
||||
|
|
||||
|
public class EpmetNacosServiceListListener implements Runnable { |
||||
|
|
||||
|
@Override |
||||
|
public void run() { |
||||
|
doRefreshServerList(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param |
||||
|
* @return |
||||
|
* @description 执行刷新 |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 16:04:49 |
||||
|
*/ |
||||
|
private synchronized void doRefreshServerList() { |
||||
|
ListView<String> serviceListView = null; |
||||
|
try { |
||||
|
serviceListView = namingService.getServicesOfServer(1, 100); |
||||
|
//启动监听
|
||||
|
if (serviceListView == null || serviceListView.getCount() == 0) { |
||||
|
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务"); |
||||
|
return; |
||||
|
} |
||||
|
List<String> serviceList = serviceListView.getData(); |
||||
|
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList); |
||||
|
|
||||
|
for (String service : serviceList) { |
||||
|
try { |
||||
|
|
||||
|
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
|
||||
|
if (observingServers.contains(service)) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
namingService.subscribe(service, new EventListener() { |
||||
|
@Override |
||||
|
public void onEvent(Event event) { |
||||
|
if (event instanceof NamingEvent) { |
||||
|
NamingEvent namingEvent = (NamingEvent) event; |
||||
|
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances()); |
||||
|
doRefreshServerList(service); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 将该服务加入到监听列表中
|
||||
|
observingServers.add(service); |
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param serviceName |
||||
|
* @return |
||||
|
* @description 刷新ServerList |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 09:29:16 |
||||
|
*/ |
||||
|
private void doRefreshServerList(String serviceName) { |
||||
|
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
|
||||
|
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
|
||||
|
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
|
||||
|
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
|
||||
|
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
|
||||
|
// try {
|
||||
|
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
|
||||
|
// restOfInitMethod.setAccessible(true);
|
||||
|
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
|
||||
|
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
|
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
|
||||
|
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
|
||||
|
// }
|
||||
|
//}
|
||||
|
|
||||
|
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
|
||||
|
// 暂且 1 try
|
||||
|
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName); |
||||
|
if (loadBalancer instanceof DynamicServerListLoadBalancer) { |
||||
|
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer; |
||||
|
dslb.updateListOfServers(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,161 @@ |
|||||
|
package com.epmet.config; |
||||
|
|
||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties; |
||||
|
import com.alibaba.nacos.api.exception.NacosException; |
||||
|
import com.alibaba.nacos.api.naming.NamingService; |
||||
|
import com.alibaba.nacos.api.naming.listener.Event; |
||||
|
import com.alibaba.nacos.api.naming.listener.EventListener; |
||||
|
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
||||
|
import com.alibaba.nacos.api.naming.pojo.ListView; |
||||
|
import com.epmet.commons.tools.exception.ExceptionUtils; |
||||
|
import com.netflix.loadbalancer.DynamicServerListLoadBalancer; |
||||
|
import com.netflix.loadbalancer.ILoadBalancer; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.concurrent.*; |
||||
|
|
||||
|
/** |
||||
|
* @author wxz |
||||
|
* @Description Nacos服务列表刷新监听注册器 |
||||
|
* @date 2021.09.22 14:33:11 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Configuration |
||||
|
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceListChangedListening", name = "enable", havingValue = "true", matchIfMissing = false) |
||||
|
public class NacosServiceListListenerRegisterer { |
||||
|
|
||||
|
public static final String REFRESH_SERVER_LIST_METHOD_NAME = "restOfInit"; |
||||
|
// 服务列表拉取间隔:10s
|
||||
|
public static final long SERVICE_LIST_PULLING_DELAY_SECONDS = 10; |
||||
|
|
||||
|
private NamingService namingService; |
||||
|
|
||||
|
private ScheduledExecutorService executor; |
||||
|
|
||||
|
@Autowired |
||||
|
private NacosDiscoveryProperties discoveryProperties; |
||||
|
|
||||
|
@Autowired |
||||
|
private SpringClientFactory springClientFactory; |
||||
|
|
||||
|
// 监听中的服务列表
|
||||
|
private List<String> observingServers = new ArrayList<>(33); |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
namingService = discoveryProperties.namingServiceInstance(); |
||||
|
// 启动监听
|
||||
|
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() { |
||||
|
@Override |
||||
|
public Thread newThread(Runnable r) { |
||||
|
Thread thread = new Thread(r); |
||||
|
thread.setDaemon(true); |
||||
|
thread.setName("NacosServiceListWatchingRegisterer"); |
||||
|
return thread; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
|
||||
|
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS); |
||||
|
} |
||||
|
|
||||
|
public class EpmetNacosServiceListListener implements Runnable { |
||||
|
|
||||
|
@Override |
||||
|
public void run() { |
||||
|
doRefreshServerList(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param |
||||
|
* @return |
||||
|
* @description 执行刷新 |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 16:04:49 |
||||
|
*/ |
||||
|
private synchronized void doRefreshServerList() { |
||||
|
ListView<String> serviceListView = null; |
||||
|
try { |
||||
|
serviceListView = namingService.getServicesOfServer(1, 100); |
||||
|
//启动监听
|
||||
|
if (serviceListView == null || serviceListView.getCount() == 0) { |
||||
|
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务"); |
||||
|
return; |
||||
|
} |
||||
|
List<String> serviceList = serviceListView.getData(); |
||||
|
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList); |
||||
|
|
||||
|
for (String service : serviceList) { |
||||
|
try { |
||||
|
|
||||
|
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
|
||||
|
if (observingServers.contains(service)) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
namingService.subscribe(service, new EventListener() { |
||||
|
@Override |
||||
|
public void onEvent(Event event) { |
||||
|
if (event instanceof NamingEvent) { |
||||
|
NamingEvent namingEvent = (NamingEvent) event; |
||||
|
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances()); |
||||
|
doRefreshServerList(service); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 将该服务加入到监听列表中
|
||||
|
observingServers.add(service); |
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param serviceName |
||||
|
* @return |
||||
|
* @description 刷新ServerList |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 09:29:16 |
||||
|
*/ |
||||
|
private void doRefreshServerList(String serviceName) { |
||||
|
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
|
||||
|
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
|
||||
|
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
|
||||
|
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
|
||||
|
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
|
||||
|
// try {
|
||||
|
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
|
||||
|
// restOfInitMethod.setAccessible(true);
|
||||
|
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
|
||||
|
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
|
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
|
||||
|
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
|
||||
|
// }
|
||||
|
//}
|
||||
|
|
||||
|
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
|
||||
|
// 暂且 1 try
|
||||
|
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName); |
||||
|
if (loadBalancer instanceof DynamicServerListLoadBalancer) { |
||||
|
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer; |
||||
|
dslb.updateListOfServers(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,161 @@ |
|||||
|
package com.epmet.config; |
||||
|
|
||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties; |
||||
|
import com.alibaba.nacos.api.exception.NacosException; |
||||
|
import com.alibaba.nacos.api.naming.NamingService; |
||||
|
import com.alibaba.nacos.api.naming.listener.Event; |
||||
|
import com.alibaba.nacos.api.naming.listener.EventListener; |
||||
|
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
||||
|
import com.alibaba.nacos.api.naming.pojo.ListView; |
||||
|
import com.epmet.commons.tools.exception.ExceptionUtils; |
||||
|
import com.netflix.loadbalancer.DynamicServerListLoadBalancer; |
||||
|
import com.netflix.loadbalancer.ILoadBalancer; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.concurrent.*; |
||||
|
|
||||
|
/** |
||||
|
* @author wxz |
||||
|
* @Description Nacos服务列表刷新监听注册器 |
||||
|
* @date 2021.09.22 14:33:11 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Configuration |
||||
|
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceListChangedListening", name = "enable", havingValue = "true", matchIfMissing = false) |
||||
|
public class NacosServiceListListenerRegisterer { |
||||
|
|
||||
|
public static final String REFRESH_SERVER_LIST_METHOD_NAME = "restOfInit"; |
||||
|
// 服务列表拉取间隔:10s
|
||||
|
public static final long SERVICE_LIST_PULLING_DELAY_SECONDS = 10; |
||||
|
|
||||
|
private NamingService namingService; |
||||
|
|
||||
|
private ScheduledExecutorService executor; |
||||
|
|
||||
|
@Autowired |
||||
|
private NacosDiscoveryProperties discoveryProperties; |
||||
|
|
||||
|
@Autowired |
||||
|
private SpringClientFactory springClientFactory; |
||||
|
|
||||
|
// 监听中的服务列表
|
||||
|
private List<String> observingServers = new ArrayList<>(33); |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
namingService = discoveryProperties.namingServiceInstance(); |
||||
|
// 启动监听
|
||||
|
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() { |
||||
|
@Override |
||||
|
public Thread newThread(Runnable r) { |
||||
|
Thread thread = new Thread(r); |
||||
|
thread.setDaemon(true); |
||||
|
thread.setName("NacosServiceListWatchingRegisterer"); |
||||
|
return thread; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
|
||||
|
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS); |
||||
|
} |
||||
|
|
||||
|
public class EpmetNacosServiceListListener implements Runnable { |
||||
|
|
||||
|
@Override |
||||
|
public void run() { |
||||
|
doRefreshServerList(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param |
||||
|
* @return |
||||
|
* @description 执行刷新 |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 16:04:49 |
||||
|
*/ |
||||
|
private synchronized void doRefreshServerList() { |
||||
|
ListView<String> serviceListView = null; |
||||
|
try { |
||||
|
serviceListView = namingService.getServicesOfServer(1, 100); |
||||
|
//启动监听
|
||||
|
if (serviceListView == null || serviceListView.getCount() == 0) { |
||||
|
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务"); |
||||
|
return; |
||||
|
} |
||||
|
List<String> serviceList = serviceListView.getData(); |
||||
|
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList); |
||||
|
|
||||
|
for (String service : serviceList) { |
||||
|
try { |
||||
|
|
||||
|
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
|
||||
|
if (observingServers.contains(service)) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
namingService.subscribe(service, new EventListener() { |
||||
|
@Override |
||||
|
public void onEvent(Event event) { |
||||
|
if (event instanceof NamingEvent) { |
||||
|
NamingEvent namingEvent = (NamingEvent) event; |
||||
|
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances()); |
||||
|
doRefreshServerList(service); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 将该服务加入到监听列表中
|
||||
|
observingServers.add(service); |
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param serviceName |
||||
|
* @return |
||||
|
* @description 刷新ServerList |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 09:29:16 |
||||
|
*/ |
||||
|
private void doRefreshServerList(String serviceName) { |
||||
|
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
|
||||
|
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
|
||||
|
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
|
||||
|
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
|
||||
|
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
|
||||
|
// try {
|
||||
|
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
|
||||
|
// restOfInitMethod.setAccessible(true);
|
||||
|
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
|
||||
|
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
|
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
|
||||
|
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
|
||||
|
// }
|
||||
|
//}
|
||||
|
|
||||
|
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
|
||||
|
// 暂且 1 try
|
||||
|
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName); |
||||
|
if (loadBalancer instanceof DynamicServerListLoadBalancer) { |
||||
|
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer; |
||||
|
dslb.updateListOfServers(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,161 @@ |
|||||
|
package com.epmet.config; |
||||
|
|
||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties; |
||||
|
import com.alibaba.nacos.api.exception.NacosException; |
||||
|
import com.alibaba.nacos.api.naming.NamingService; |
||||
|
import com.alibaba.nacos.api.naming.listener.Event; |
||||
|
import com.alibaba.nacos.api.naming.listener.EventListener; |
||||
|
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
||||
|
import com.alibaba.nacos.api.naming.pojo.ListView; |
||||
|
import com.epmet.commons.tools.exception.ExceptionUtils; |
||||
|
import com.netflix.loadbalancer.DynamicServerListLoadBalancer; |
||||
|
import com.netflix.loadbalancer.ILoadBalancer; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.concurrent.*; |
||||
|
|
||||
|
/** |
||||
|
* @author wxz |
||||
|
* @Description Nacos服务列表刷新监听注册器 |
||||
|
* @date 2021.09.22 14:33:11 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Configuration |
||||
|
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceListChangedListening", name = "enable", havingValue = "true", matchIfMissing = false) |
||||
|
public class NacosServiceListListenerRegisterer { |
||||
|
|
||||
|
public static final String REFRESH_SERVER_LIST_METHOD_NAME = "restOfInit"; |
||||
|
// 服务列表拉取间隔:10s
|
||||
|
public static final long SERVICE_LIST_PULLING_DELAY_SECONDS = 10; |
||||
|
|
||||
|
private NamingService namingService; |
||||
|
|
||||
|
private ScheduledExecutorService executor; |
||||
|
|
||||
|
@Autowired |
||||
|
private NacosDiscoveryProperties discoveryProperties; |
||||
|
|
||||
|
@Autowired |
||||
|
private SpringClientFactory springClientFactory; |
||||
|
|
||||
|
// 监听中的服务列表
|
||||
|
private List<String> observingServers = new ArrayList<>(33); |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
namingService = discoveryProperties.namingServiceInstance(); |
||||
|
// 启动监听
|
||||
|
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() { |
||||
|
@Override |
||||
|
public Thread newThread(Runnable r) { |
||||
|
Thread thread = new Thread(r); |
||||
|
thread.setDaemon(true); |
||||
|
thread.setName("NacosServiceListWatchingRegisterer"); |
||||
|
return thread; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
|
||||
|
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS); |
||||
|
} |
||||
|
|
||||
|
public class EpmetNacosServiceListListener implements Runnable { |
||||
|
|
||||
|
@Override |
||||
|
public void run() { |
||||
|
doRefreshServerList(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param |
||||
|
* @return |
||||
|
* @description 执行刷新 |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 16:04:49 |
||||
|
*/ |
||||
|
private synchronized void doRefreshServerList() { |
||||
|
ListView<String> serviceListView = null; |
||||
|
try { |
||||
|
serviceListView = namingService.getServicesOfServer(1, 100); |
||||
|
//启动监听
|
||||
|
if (serviceListView == null || serviceListView.getCount() == 0) { |
||||
|
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务"); |
||||
|
return; |
||||
|
} |
||||
|
List<String> serviceList = serviceListView.getData(); |
||||
|
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList); |
||||
|
|
||||
|
for (String service : serviceList) { |
||||
|
try { |
||||
|
|
||||
|
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
|
||||
|
if (observingServers.contains(service)) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
namingService.subscribe(service, new EventListener() { |
||||
|
@Override |
||||
|
public void onEvent(Event event) { |
||||
|
if (event instanceof NamingEvent) { |
||||
|
NamingEvent namingEvent = (NamingEvent) event; |
||||
|
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances()); |
||||
|
doRefreshServerList(service); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 将该服务加入到监听列表中
|
||||
|
observingServers.add(service); |
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param serviceName |
||||
|
* @return |
||||
|
* @description 刷新ServerList |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 09:29:16 |
||||
|
*/ |
||||
|
private void doRefreshServerList(String serviceName) { |
||||
|
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
|
||||
|
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
|
||||
|
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
|
||||
|
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
|
||||
|
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
|
||||
|
// try {
|
||||
|
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
|
||||
|
// restOfInitMethod.setAccessible(true);
|
||||
|
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
|
||||
|
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
|
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
|
||||
|
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
|
||||
|
// }
|
||||
|
//}
|
||||
|
|
||||
|
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
|
||||
|
// 暂且 1 try
|
||||
|
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName); |
||||
|
if (loadBalancer instanceof DynamicServerListLoadBalancer) { |
||||
|
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer; |
||||
|
dslb.updateListOfServers(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,161 @@ |
|||||
|
package com.epmet.config; |
||||
|
|
||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties; |
||||
|
import com.alibaba.nacos.api.exception.NacosException; |
||||
|
import com.alibaba.nacos.api.naming.NamingService; |
||||
|
import com.alibaba.nacos.api.naming.listener.Event; |
||||
|
import com.alibaba.nacos.api.naming.listener.EventListener; |
||||
|
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
||||
|
import com.alibaba.nacos.api.naming.pojo.ListView; |
||||
|
import com.epmet.commons.tools.exception.ExceptionUtils; |
||||
|
import com.netflix.loadbalancer.DynamicServerListLoadBalancer; |
||||
|
import com.netflix.loadbalancer.ILoadBalancer; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.concurrent.*; |
||||
|
|
||||
|
/** |
||||
|
* @author wxz |
||||
|
* @Description Nacos服务列表刷新监听注册器 |
||||
|
* @date 2021.09.22 14:33:11 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Configuration |
||||
|
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceListChangedListening", name = "enable", havingValue = "true", matchIfMissing = false) |
||||
|
public class NacosServiceListListenerRegisterer { |
||||
|
|
||||
|
public static final String REFRESH_SERVER_LIST_METHOD_NAME = "restOfInit"; |
||||
|
// 服务列表拉取间隔:10s
|
||||
|
public static final long SERVICE_LIST_PULLING_DELAY_SECONDS = 10; |
||||
|
|
||||
|
private NamingService namingService; |
||||
|
|
||||
|
private ScheduledExecutorService executor; |
||||
|
|
||||
|
@Autowired |
||||
|
private NacosDiscoveryProperties discoveryProperties; |
||||
|
|
||||
|
@Autowired |
||||
|
private SpringClientFactory springClientFactory; |
||||
|
|
||||
|
// 监听中的服务列表
|
||||
|
private List<String> observingServers = new ArrayList<>(33); |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
namingService = discoveryProperties.namingServiceInstance(); |
||||
|
// 启动监听
|
||||
|
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() { |
||||
|
@Override |
||||
|
public Thread newThread(Runnable r) { |
||||
|
Thread thread = new Thread(r); |
||||
|
thread.setDaemon(true); |
||||
|
thread.setName("NacosServiceListWatchingRegisterer"); |
||||
|
return thread; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
|
||||
|
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS); |
||||
|
} |
||||
|
|
||||
|
public class EpmetNacosServiceListListener implements Runnable { |
||||
|
|
||||
|
@Override |
||||
|
public void run() { |
||||
|
doRefreshServerList(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param |
||||
|
* @return |
||||
|
* @description 执行刷新 |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 16:04:49 |
||||
|
*/ |
||||
|
private synchronized void doRefreshServerList() { |
||||
|
ListView<String> serviceListView = null; |
||||
|
try { |
||||
|
serviceListView = namingService.getServicesOfServer(1, 100); |
||||
|
//启动监听
|
||||
|
if (serviceListView == null || serviceListView.getCount() == 0) { |
||||
|
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务"); |
||||
|
return; |
||||
|
} |
||||
|
List<String> serviceList = serviceListView.getData(); |
||||
|
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList); |
||||
|
|
||||
|
for (String service : serviceList) { |
||||
|
try { |
||||
|
|
||||
|
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
|
||||
|
if (observingServers.contains(service)) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
namingService.subscribe(service, new EventListener() { |
||||
|
@Override |
||||
|
public void onEvent(Event event) { |
||||
|
if (event instanceof NamingEvent) { |
||||
|
NamingEvent namingEvent = (NamingEvent) event; |
||||
|
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances()); |
||||
|
doRefreshServerList(service); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 将该服务加入到监听列表中
|
||||
|
observingServers.add(service); |
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param serviceName |
||||
|
* @return |
||||
|
* @description 刷新ServerList |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 09:29:16 |
||||
|
*/ |
||||
|
private void doRefreshServerList(String serviceName) { |
||||
|
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
|
||||
|
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
|
||||
|
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
|
||||
|
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
|
||||
|
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
|
||||
|
// try {
|
||||
|
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
|
||||
|
// restOfInitMethod.setAccessible(true);
|
||||
|
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
|
||||
|
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
|
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
|
||||
|
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
|
||||
|
// }
|
||||
|
//}
|
||||
|
|
||||
|
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
|
||||
|
// 暂且 1 try
|
||||
|
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName); |
||||
|
if (loadBalancer instanceof DynamicServerListLoadBalancer) { |
||||
|
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer; |
||||
|
dslb.updateListOfServers(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,161 @@ |
|||||
|
package com.epmet.config; |
||||
|
|
||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties; |
||||
|
import com.alibaba.nacos.api.exception.NacosException; |
||||
|
import com.alibaba.nacos.api.naming.NamingService; |
||||
|
import com.alibaba.nacos.api.naming.listener.Event; |
||||
|
import com.alibaba.nacos.api.naming.listener.EventListener; |
||||
|
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
||||
|
import com.alibaba.nacos.api.naming.pojo.ListView; |
||||
|
import com.epmet.commons.tools.exception.ExceptionUtils; |
||||
|
import com.netflix.loadbalancer.DynamicServerListLoadBalancer; |
||||
|
import com.netflix.loadbalancer.ILoadBalancer; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.concurrent.*; |
||||
|
|
||||
|
/** |
||||
|
* @author wxz |
||||
|
* @Description Nacos服务列表刷新监听注册器 |
||||
|
* @date 2021.09.22 14:33:11 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Configuration |
||||
|
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceListChangedListening", name = "enable", havingValue = "true", matchIfMissing = false) |
||||
|
public class NacosServiceListListenerRegisterer { |
||||
|
|
||||
|
public static final String REFRESH_SERVER_LIST_METHOD_NAME = "restOfInit"; |
||||
|
// 服务列表拉取间隔:10s
|
||||
|
public static final long SERVICE_LIST_PULLING_DELAY_SECONDS = 10; |
||||
|
|
||||
|
private NamingService namingService; |
||||
|
|
||||
|
private ScheduledExecutorService executor; |
||||
|
|
||||
|
@Autowired |
||||
|
private NacosDiscoveryProperties discoveryProperties; |
||||
|
|
||||
|
@Autowired |
||||
|
private SpringClientFactory springClientFactory; |
||||
|
|
||||
|
// 监听中的服务列表
|
||||
|
private List<String> observingServers = new ArrayList<>(33); |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
namingService = discoveryProperties.namingServiceInstance(); |
||||
|
// 启动监听
|
||||
|
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() { |
||||
|
@Override |
||||
|
public Thread newThread(Runnable r) { |
||||
|
Thread thread = new Thread(r); |
||||
|
thread.setDaemon(true); |
||||
|
thread.setName("NacosServiceListWatchingRegisterer"); |
||||
|
return thread; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
|
||||
|
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS); |
||||
|
} |
||||
|
|
||||
|
public class EpmetNacosServiceListListener implements Runnable { |
||||
|
|
||||
|
@Override |
||||
|
public void run() { |
||||
|
doRefreshServerList(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param |
||||
|
* @return |
||||
|
* @description 执行刷新 |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 16:04:49 |
||||
|
*/ |
||||
|
private synchronized void doRefreshServerList() { |
||||
|
ListView<String> serviceListView = null; |
||||
|
try { |
||||
|
serviceListView = namingService.getServicesOfServer(1, 100); |
||||
|
//启动监听
|
||||
|
if (serviceListView == null || serviceListView.getCount() == 0) { |
||||
|
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务"); |
||||
|
return; |
||||
|
} |
||||
|
List<String> serviceList = serviceListView.getData(); |
||||
|
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList); |
||||
|
|
||||
|
for (String service : serviceList) { |
||||
|
try { |
||||
|
|
||||
|
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
|
||||
|
if (observingServers.contains(service)) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
namingService.subscribe(service, new EventListener() { |
||||
|
@Override |
||||
|
public void onEvent(Event event) { |
||||
|
if (event instanceof NamingEvent) { |
||||
|
NamingEvent namingEvent = (NamingEvent) event; |
||||
|
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances()); |
||||
|
doRefreshServerList(service); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 将该服务加入到监听列表中
|
||||
|
observingServers.add(service); |
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param serviceName |
||||
|
* @return |
||||
|
* @description 刷新ServerList |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 09:29:16 |
||||
|
*/ |
||||
|
private void doRefreshServerList(String serviceName) { |
||||
|
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
|
||||
|
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
|
||||
|
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
|
||||
|
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
|
||||
|
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
|
||||
|
// try {
|
||||
|
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
|
||||
|
// restOfInitMethod.setAccessible(true);
|
||||
|
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
|
||||
|
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
|
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
|
||||
|
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
|
||||
|
// }
|
||||
|
//}
|
||||
|
|
||||
|
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
|
||||
|
// 暂且 1 try
|
||||
|
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName); |
||||
|
if (loadBalancer instanceof DynamicServerListLoadBalancer) { |
||||
|
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer; |
||||
|
dslb.updateListOfServers(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,161 @@ |
|||||
|
package com.epmet.config; |
||||
|
|
||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties; |
||||
|
import com.alibaba.nacos.api.exception.NacosException; |
||||
|
import com.alibaba.nacos.api.naming.NamingService; |
||||
|
import com.alibaba.nacos.api.naming.listener.Event; |
||||
|
import com.alibaba.nacos.api.naming.listener.EventListener; |
||||
|
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
||||
|
import com.alibaba.nacos.api.naming.pojo.ListView; |
||||
|
import com.epmet.commons.tools.exception.ExceptionUtils; |
||||
|
import com.netflix.loadbalancer.DynamicServerListLoadBalancer; |
||||
|
import com.netflix.loadbalancer.ILoadBalancer; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.concurrent.*; |
||||
|
|
||||
|
/** |
||||
|
* @author wxz |
||||
|
* @Description Nacos服务列表刷新监听注册器 |
||||
|
* @date 2021.09.22 14:33:11 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Configuration |
||||
|
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceListChangedListening", name = "enable", havingValue = "true", matchIfMissing = false) |
||||
|
public class NacosServiceListListenerRegisterer { |
||||
|
|
||||
|
public static final String REFRESH_SERVER_LIST_METHOD_NAME = "restOfInit"; |
||||
|
// 服务列表拉取间隔:10s
|
||||
|
public static final long SERVICE_LIST_PULLING_DELAY_SECONDS = 10; |
||||
|
|
||||
|
private NamingService namingService; |
||||
|
|
||||
|
private ScheduledExecutorService executor; |
||||
|
|
||||
|
@Autowired |
||||
|
private NacosDiscoveryProperties discoveryProperties; |
||||
|
|
||||
|
@Autowired |
||||
|
private SpringClientFactory springClientFactory; |
||||
|
|
||||
|
// 监听中的服务列表
|
||||
|
private List<String> observingServers = new ArrayList<>(33); |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
namingService = discoveryProperties.namingServiceInstance(); |
||||
|
// 启动监听
|
||||
|
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() { |
||||
|
@Override |
||||
|
public Thread newThread(Runnable r) { |
||||
|
Thread thread = new Thread(r); |
||||
|
thread.setDaemon(true); |
||||
|
thread.setName("NacosServiceListWatchingRegisterer"); |
||||
|
return thread; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
|
||||
|
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS); |
||||
|
} |
||||
|
|
||||
|
public class EpmetNacosServiceListListener implements Runnable { |
||||
|
|
||||
|
@Override |
||||
|
public void run() { |
||||
|
doRefreshServerList(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param |
||||
|
* @return |
||||
|
* @description 执行刷新 |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 16:04:49 |
||||
|
*/ |
||||
|
private synchronized void doRefreshServerList() { |
||||
|
ListView<String> serviceListView = null; |
||||
|
try { |
||||
|
serviceListView = namingService.getServicesOfServer(1, 100); |
||||
|
//启动监听
|
||||
|
if (serviceListView == null || serviceListView.getCount() == 0) { |
||||
|
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务"); |
||||
|
return; |
||||
|
} |
||||
|
List<String> serviceList = serviceListView.getData(); |
||||
|
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList); |
||||
|
|
||||
|
for (String service : serviceList) { |
||||
|
try { |
||||
|
|
||||
|
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
|
||||
|
if (observingServers.contains(service)) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
namingService.subscribe(service, new EventListener() { |
||||
|
@Override |
||||
|
public void onEvent(Event event) { |
||||
|
if (event instanceof NamingEvent) { |
||||
|
NamingEvent namingEvent = (NamingEvent) event; |
||||
|
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances()); |
||||
|
doRefreshServerList(service); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 将该服务加入到监听列表中
|
||||
|
observingServers.add(service); |
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param serviceName |
||||
|
* @return |
||||
|
* @description 刷新ServerList |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 09:29:16 |
||||
|
*/ |
||||
|
private void doRefreshServerList(String serviceName) { |
||||
|
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
|
||||
|
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
|
||||
|
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
|
||||
|
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
|
||||
|
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
|
||||
|
// try {
|
||||
|
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
|
||||
|
// restOfInitMethod.setAccessible(true);
|
||||
|
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
|
||||
|
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
|
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
|
||||
|
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
|
||||
|
// }
|
||||
|
//}
|
||||
|
|
||||
|
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
|
||||
|
// 暂且 1 try
|
||||
|
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName); |
||||
|
if (loadBalancer instanceof DynamicServerListLoadBalancer) { |
||||
|
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer; |
||||
|
dslb.updateListOfServers(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,161 @@ |
|||||
|
package com.epmet.config; |
||||
|
|
||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties; |
||||
|
import com.alibaba.nacos.api.exception.NacosException; |
||||
|
import com.alibaba.nacos.api.naming.NamingService; |
||||
|
import com.alibaba.nacos.api.naming.listener.Event; |
||||
|
import com.alibaba.nacos.api.naming.listener.EventListener; |
||||
|
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
||||
|
import com.alibaba.nacos.api.naming.pojo.ListView; |
||||
|
import com.epmet.commons.tools.exception.ExceptionUtils; |
||||
|
import com.netflix.loadbalancer.DynamicServerListLoadBalancer; |
||||
|
import com.netflix.loadbalancer.ILoadBalancer; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.concurrent.*; |
||||
|
|
||||
|
/** |
||||
|
* @author wxz |
||||
|
* @Description Nacos服务列表刷新监听注册器 |
||||
|
* @date 2021.09.22 14:33:11 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Configuration |
||||
|
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceListChangedListening", name = "enable", havingValue = "true", matchIfMissing = false) |
||||
|
public class NacosServiceListListenerRegisterer { |
||||
|
|
||||
|
public static final String REFRESH_SERVER_LIST_METHOD_NAME = "restOfInit"; |
||||
|
// 服务列表拉取间隔:10s
|
||||
|
public static final long SERVICE_LIST_PULLING_DELAY_SECONDS = 10; |
||||
|
|
||||
|
private NamingService namingService; |
||||
|
|
||||
|
private ScheduledExecutorService executor; |
||||
|
|
||||
|
@Autowired |
||||
|
private NacosDiscoveryProperties discoveryProperties; |
||||
|
|
||||
|
@Autowired |
||||
|
private SpringClientFactory springClientFactory; |
||||
|
|
||||
|
// 监听中的服务列表
|
||||
|
private List<String> observingServers = new ArrayList<>(33); |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
namingService = discoveryProperties.namingServiceInstance(); |
||||
|
// 启动监听
|
||||
|
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() { |
||||
|
@Override |
||||
|
public Thread newThread(Runnable r) { |
||||
|
Thread thread = new Thread(r); |
||||
|
thread.setDaemon(true); |
||||
|
thread.setName("NacosServiceListWatchingRegisterer"); |
||||
|
return thread; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
|
||||
|
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS); |
||||
|
} |
||||
|
|
||||
|
public class EpmetNacosServiceListListener implements Runnable { |
||||
|
|
||||
|
@Override |
||||
|
public void run() { |
||||
|
doRefreshServerList(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param |
||||
|
* @return |
||||
|
* @description 执行刷新 |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 16:04:49 |
||||
|
*/ |
||||
|
private synchronized void doRefreshServerList() { |
||||
|
ListView<String> serviceListView = null; |
||||
|
try { |
||||
|
serviceListView = namingService.getServicesOfServer(1, 100); |
||||
|
//启动监听
|
||||
|
if (serviceListView == null || serviceListView.getCount() == 0) { |
||||
|
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务"); |
||||
|
return; |
||||
|
} |
||||
|
List<String> serviceList = serviceListView.getData(); |
||||
|
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList); |
||||
|
|
||||
|
for (String service : serviceList) { |
||||
|
try { |
||||
|
|
||||
|
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
|
||||
|
if (observingServers.contains(service)) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
namingService.subscribe(service, new EventListener() { |
||||
|
@Override |
||||
|
public void onEvent(Event event) { |
||||
|
if (event instanceof NamingEvent) { |
||||
|
NamingEvent namingEvent = (NamingEvent) event; |
||||
|
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances()); |
||||
|
doRefreshServerList(service); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 将该服务加入到监听列表中
|
||||
|
observingServers.add(service); |
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} catch (NacosException e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param serviceName |
||||
|
* @return |
||||
|
* @description 刷新ServerList |
||||
|
* @author wxz |
||||
|
* @date 2021.09.22 09:29:16 |
||||
|
*/ |
||||
|
private void doRefreshServerList(String serviceName) { |
||||
|
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
|
||||
|
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
|
||||
|
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
|
||||
|
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
|
||||
|
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
|
||||
|
// try {
|
||||
|
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
|
||||
|
// restOfInitMethod.setAccessible(true);
|
||||
|
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
|
||||
|
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
|
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
|
||||
|
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
|
||||
|
// }
|
||||
|
//}
|
||||
|
|
||||
|
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
|
||||
|
// 暂且 1 try
|
||||
|
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName); |
||||
|
if (loadBalancer instanceof DynamicServerListLoadBalancer) { |
||||
|
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer; |
||||
|
dslb.updateListOfServers(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue