diff --git a/epmet-admin/epmet-admin-server/pom.xml b/epmet-admin/epmet-admin-server/pom.xml
index 43a91d2085..e1b1324219 100644
--- a/epmet-admin/epmet-admin-server/pom.xml
+++ b/epmet-admin/epmet-admin-server/pom.xml
@@ -132,6 +132,8 @@
false
+
+ true
false
@@ -170,6 +172,9 @@
false
+
+ false
+
false
@@ -203,6 +208,8 @@
false
+
+ true
true
@@ -238,6 +245,9 @@
false
+
+ false
+
true
diff --git a/epmet-admin/epmet-admin-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-admin/epmet-admin-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-admin/epmet-admin-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-admin/epmet-admin-server/src/main/resources/bootstrap.yml b/epmet-admin/epmet-admin-server/src/main/resources/bootstrap.yml
index 74c6bc2567..fc45940737 100644
--- a/epmet-admin/epmet-admin-server/src/main/resources/bootstrap.yml
+++ b/epmet-admin/epmet-admin-server/src/main/resources/bootstrap.yml
@@ -61,6 +61,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-auth/pom.xml b/epmet-auth/pom.xml
index 7e99e2054e..ebb6efe0ab 100644
--- a/epmet-auth/pom.xml
+++ b/epmet-auth/pom.xml
@@ -183,6 +183,8 @@
false
+
+ true
wxcb6ce2ed0c5ae54c
@@ -238,6 +240,8 @@
false
+
+ false
wxcb6ce2ed0c5ae54c
@@ -290,6 +294,8 @@
false
+
+ true
wxcb6ce2ed0c5ae54c
@@ -345,6 +351,9 @@
false
+
+ false
+
wxcb6ce2ed0c5ae54c
c7f74941ee97fa9b2e1065772d34c397
diff --git a/epmet-auth/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-auth/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-auth/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-gateway/pom.xml b/epmet-gateway/pom.xml
index 7f9b4cbe40..b45631716d 100644
--- a/epmet-gateway/pom.xml
+++ b/epmet-gateway/pom.xml
@@ -124,6 +124,9 @@
false
+
+ true
+
@@ -255,6 +258,9 @@
false
+
+
+ false
@@ -389,6 +395,9 @@
false
+
+ true
+
lb://epmet-auth-server
@@ -488,6 +497,10 @@
false
+
+
+ false
+
lb://epmet-auth-server
diff --git a/epmet-gateway/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-gateway/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-gateway/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-gateway/src/main/resources/bootstrap.yml b/epmet-gateway/src/main/resources/bootstrap.yml
index ca78ab64aa..8426a6c577 100644
--- a/epmet-gateway/src/main/resources/bootstrap.yml
+++ b/epmet-gateway/src/main/resources/bootstrap.yml
@@ -358,6 +358,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
@@ -427,6 +429,7 @@ feign:
config:
default:
loggerLevel: BASIC
+ readTimeout: 600000
okhttp:
enabled: true
diff --git a/epmet-module/data-aggregator/data-aggregator-server/pom.xml b/epmet-module/data-aggregator/data-aggregator-server/pom.xml
index 4dd3dae05c..78315574e7 100644
--- a/epmet-module/data-aggregator/data-aggregator-server/pom.xml
+++ b/epmet-module/data-aggregator/data-aggregator-server/pom.xml
@@ -222,6 +222,8 @@
false
+
+ true
false
@@ -336,6 +338,8 @@
false
+
+ false
false
@@ -450,6 +454,8 @@
false
+
+ true
true
@@ -565,6 +571,9 @@
false
+
+ false
+
true
diff --git a/epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/config/NacosServiceListListenerRegisterer.java b/epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..a97d477908
--- /dev/null
+++ b/epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/data-aggregator/data-aggregator-server/src/main/resources/bootstrap.yml b/epmet-module/data-aggregator/data-aggregator-server/src/main/resources/bootstrap.yml
index 102666f3d7..934dcae2c5 100644
--- a/epmet-module/data-aggregator/data-aggregator-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/data-aggregator/data-aggregator-server/src/main/resources/bootstrap.yml
@@ -37,6 +37,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/data-report/data-report-server/pom.xml b/epmet-module/data-report/data-report-server/pom.xml
index 9b34a26b59..2afe5ea326 100644
--- a/epmet-module/data-report/data-report-server/pom.xml
+++ b/epmet-module/data-report/data-report-server/pom.xml
@@ -167,6 +167,8 @@
false
+
+ true
false
@@ -219,6 +221,8 @@
false
+
+ false
false
@@ -271,6 +275,8 @@
false
+
+ true
true
@@ -323,6 +329,9 @@
false
+
+ false
+
true
diff --git a/epmet-module/data-report/data-report-server/src/main/java/com/epmet/datareport/config/NacosServiceListListenerRegisterer.java b/epmet-module/data-report/data-report-server/src/main/java/com/epmet/datareport/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..37ad4c96f7
--- /dev/null
+++ b/epmet-module/data-report/data-report-server/src/main/java/com/epmet/datareport/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/data-report/data-report-server/src/main/resources/bootstrap.yml b/epmet-module/data-report/data-report-server/src/main/resources/bootstrap.yml
index 3ecb0ec3d1..2ee366e369 100644
--- a/epmet-module/data-report/data-report-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/data-report/data-report-server/src/main/resources/bootstrap.yml
@@ -37,6 +37,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/data-statistical/data-statistical-server/pom.xml b/epmet-module/data-statistical/data-statistical-server/pom.xml
index 0299d53d42..cf5f58e634 100644
--- a/epmet-module/data-statistical/data-statistical-server/pom.xml
+++ b/epmet-module/data-statistical/data-statistical-server/pom.xml
@@ -241,6 +241,8 @@
false
+
+ true
false
@@ -361,6 +363,8 @@
false
+
+ false
false
@@ -481,6 +485,8 @@
false
+
+ true
false
@@ -597,6 +603,8 @@
false
+
+ false
false
diff --git a/epmet-module/data-statistical/data-statistical-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/data-statistical/data-statistical-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/data-statistical/data-statistical-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/data-statistical/data-statistical-server/src/main/resources/bootstrap.yml b/epmet-module/data-statistical/data-statistical-server/src/main/resources/bootstrap.yml
index 7723414608..1f2089ea27 100644
--- a/epmet-module/data-statistical/data-statistical-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/data-statistical/data-statistical-server/src/main/resources/bootstrap.yml
@@ -37,6 +37,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/epmet-activiti/epmet-activiti-server/pom.xml b/epmet-module/epmet-activiti/epmet-activiti-server/pom.xml
index b87470fd09..39153b082b 100644
--- a/epmet-module/epmet-activiti/epmet-activiti-server/pom.xml
+++ b/epmet-module/epmet-activiti/epmet-activiti-server/pom.xml
@@ -181,6 +181,8 @@
false
+
+ true
false
@@ -213,6 +215,8 @@
false
+
+ false
false
@@ -242,6 +246,8 @@
false
+
+ true
true
@@ -271,6 +277,8 @@
false
+
+ false
true
diff --git a/epmet-module/epmet-activiti/epmet-activiti-server/src/main/resources/bootstrap.yml b/epmet-module/epmet-activiti/epmet-activiti-server/src/main/resources/bootstrap.yml
index 811f0c352b..f31026085f 100644
--- a/epmet-module/epmet-activiti/epmet-activiti-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/epmet-activiti/epmet-activiti-server/src/main/resources/bootstrap.yml
@@ -50,6 +50,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/epmet-common-service/common-service-server/pom.xml b/epmet-module/epmet-common-service/common-service-server/pom.xml
index 23706fdf68..5e163bafa0 100644
--- a/epmet-module/epmet-common-service/common-service-server/pom.xml
+++ b/epmet-module/epmet-common-service/common-service-server/pom.xml
@@ -123,6 +123,8 @@
false
+
+ true
false
@@ -169,6 +171,8 @@
false
+
+ false
false
@@ -213,6 +217,8 @@
false
+
+ true
true
@@ -254,6 +260,8 @@
false
+
+ false
true
diff --git a/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/epmet-common-service/common-service-server/src/main/resources/bootstrap.yml b/epmet-module/epmet-common-service/common-service-server/src/main/resources/bootstrap.yml
index ff4ec82dcf..3da9f56074 100644
--- a/epmet-module/epmet-common-service/common-service-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/epmet-common-service/common-service-server/src/main/resources/bootstrap.yml
@@ -49,6 +49,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/epmet-demo/epmet-demo-server/pom.xml b/epmet-module/epmet-demo/epmet-demo-server/pom.xml
index b877c0df18..00a03e4aab 100644
--- a/epmet-module/epmet-demo/epmet-demo-server/pom.xml
+++ b/epmet-module/epmet-demo/epmet-demo-server/pom.xml
@@ -127,6 +127,8 @@
false
+
+ true
@@ -136,7 +138,7 @@
-->
8088
- dev
+ test
@@ -157,6 +159,9 @@
false
+
+
+ true
diff --git a/epmet-module/epmet-demo/epmet-demo-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/epmet-demo/epmet-demo-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/epmet-demo/epmet-demo-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/epmet-demo/epmet-demo-server/src/main/resources/bootstrap.yml b/epmet-module/epmet-demo/epmet-demo-server/src/main/resources/bootstrap.yml
index b9cf8dd559..59feaf2641 100644
--- a/epmet-module/epmet-demo/epmet-demo-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/epmet-demo/epmet-demo-server/src/main/resources/bootstrap.yml
@@ -40,6 +40,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/epmet-ext/epmet-ext-server/pom.xml b/epmet-module/epmet-ext/epmet-ext-server/pom.xml
index d57399d632..4df0f42dc6 100644
--- a/epmet-module/epmet-ext/epmet-ext-server/pom.xml
+++ b/epmet-module/epmet-ext/epmet-ext-server/pom.xml
@@ -215,6 +215,8 @@
false
+
+ true
false
@@ -254,6 +256,8 @@
false
+
+ false
false
@@ -293,6 +297,8 @@
false
+
+ true
true
@@ -333,6 +339,8 @@
false
+
+ false
true
diff --git a/epmet-module/epmet-ext/epmet-ext-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/epmet-ext/epmet-ext-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/epmet-ext/epmet-ext-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/epmet-ext/epmet-ext-server/src/main/resources/bootstrap.yml b/epmet-module/epmet-ext/epmet-ext-server/src/main/resources/bootstrap.yml
index 881881db27..bf9a797c20 100644
--- a/epmet-module/epmet-ext/epmet-ext-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/epmet-ext/epmet-ext-server/src/main/resources/bootstrap.yml
@@ -35,6 +35,8 @@ spring:
namespace: @nacos.discovery.namespace@
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/epmet-heart/epmet-heart-server/pom.xml b/epmet-module/epmet-heart/epmet-heart-server/pom.xml
index db8b452d8a..5034d0c960 100644
--- a/epmet-module/epmet-heart/epmet-heart-server/pom.xml
+++ b/epmet-module/epmet-heart/epmet-heart-server/pom.xml
@@ -133,6 +133,8 @@
false
+
+ true
false
https://epmet-dev.elinkservice.cn/api/epmetscan/api
@@ -174,6 +176,8 @@
false
+
+ false
false
https://epmet-dev.elinkservice.cn/api/epmetscan/api
@@ -215,6 +219,8 @@
false
+
+ true
true
https://epmet-dev.elinkservice.cn/api/epmetscan/api
@@ -256,6 +262,8 @@
false
+
+ false
true
https://epmet-open.elinkservice.cn/api/epmetscan/api
diff --git a/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/epmet-heart/epmet-heart-server/src/main/resources/bootstrap.yml b/epmet-module/epmet-heart/epmet-heart-server/src/main/resources/bootstrap.yml
index 8fe49b4ea0..fe4ff2e5fa 100644
--- a/epmet-module/epmet-heart/epmet-heart-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/epmet-heart/epmet-heart-server/src/main/resources/bootstrap.yml
@@ -37,6 +37,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/epmet-job/epmet-job-server/pom.xml b/epmet-module/epmet-job/epmet-job-server/pom.xml
index 8acef0b159..1466c3b309 100644
--- a/epmet-module/epmet-job/epmet-job-server/pom.xml
+++ b/epmet-module/epmet-job/epmet-job-server/pom.xml
@@ -136,6 +136,8 @@
false
+
+ true
false
@@ -171,6 +173,8 @@
false
+
+ false
false
@@ -206,6 +210,8 @@
false
+
+ true
true
@@ -239,6 +245,9 @@
false
+
+ false
+
true
diff --git a/epmet-module/epmet-job/epmet-job-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/epmet-job/epmet-job-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/epmet-job/epmet-job-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/epmet-job/epmet-job-server/src/main/resources/bootstrap.yml b/epmet-module/epmet-job/epmet-job-server/src/main/resources/bootstrap.yml
index e0dc62b7f0..0b590717e1 100644
--- a/epmet-module/epmet-job/epmet-job-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/epmet-job/epmet-job-server/src/main/resources/bootstrap.yml
@@ -49,6 +49,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/epmet-message/epmet-message-server/pom.xml b/epmet-module/epmet-message/epmet-message-server/pom.xml
index 6351be0479..04f76fb262 100644
--- a/epmet-module/epmet-message/epmet-message-server/pom.xml
+++ b/epmet-module/epmet-message/epmet-message-server/pom.xml
@@ -182,6 +182,8 @@
false
+
+ true
false
@@ -231,6 +233,8 @@
false
+
+ false
false
@@ -279,6 +283,8 @@
false
+
+ true
true
@@ -325,6 +331,9 @@
false
+
+ false
+
true
diff --git a/epmet-module/epmet-message/epmet-message-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/epmet-message/epmet-message-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/epmet-message/epmet-message-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/epmet-message/epmet-message-server/src/main/resources/bootstrap.yml b/epmet-module/epmet-message/epmet-message-server/src/main/resources/bootstrap.yml
index 03945c0ebf..f4f88d87ca 100644
--- a/epmet-module/epmet-message/epmet-message-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/epmet-message/epmet-message-server/src/main/resources/bootstrap.yml
@@ -40,6 +40,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/epmet-oss/epmet-oss-server/pom.xml b/epmet-module/epmet-oss/epmet-oss-server/pom.xml
index 5d01eddb04..324417a12e 100644
--- a/epmet-module/epmet-oss/epmet-oss-server/pom.xml
+++ b/epmet-module/epmet-oss/epmet-oss-server/pom.xml
@@ -141,6 +141,8 @@
false
+
+ true
false
@@ -180,6 +182,8 @@
false
+
+ false
false
@@ -218,6 +222,8 @@
false
+
+ true
true
@@ -253,6 +259,8 @@
false
+
+ false
true
diff --git a/epmet-module/epmet-oss/epmet-oss-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/epmet-oss/epmet-oss-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/epmet-oss/epmet-oss-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/epmet-oss/epmet-oss-server/src/main/resources/bootstrap.yml b/epmet-module/epmet-oss/epmet-oss-server/src/main/resources/bootstrap.yml
index 3bfe0d68bc..1b939a5edd 100644
--- a/epmet-module/epmet-oss/epmet-oss-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/epmet-oss/epmet-oss-server/src/main/resources/bootstrap.yml
@@ -54,6 +54,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/epmet-point/epmet-point-server/pom.xml b/epmet-module/epmet-point/epmet-point-server/pom.xml
index 9bd33f0439..89aff1267e 100644
--- a/epmet-module/epmet-point/epmet-point-server/pom.xml
+++ b/epmet-module/epmet-point/epmet-point-server/pom.xml
@@ -154,6 +154,8 @@
false
+
+ true
false
@@ -195,6 +197,8 @@
false
+
+ true
false
@@ -236,6 +240,8 @@
false
+
+ true
true
@@ -277,6 +283,8 @@
false
+
+ false
true
diff --git a/epmet-module/epmet-point/epmet-point-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/epmet-point/epmet-point-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/epmet-point/epmet-point-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/epmet-point/epmet-point-server/src/main/resources/bootstrap.yml b/epmet-module/epmet-point/epmet-point-server/src/main/resources/bootstrap.yml
index 08cae6a575..af068df15d 100644
--- a/epmet-module/epmet-point/epmet-point-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/epmet-point/epmet-point-server/src/main/resources/bootstrap.yml
@@ -37,6 +37,9 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ # 是否开启服务实例列表变更监听
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
@@ -113,6 +116,7 @@ hystrix:
ribbon:
ReadTimeout: 300000
ConnectTimeout: 300000
+# ServerListRefreshInterval: 5000
#pageHelper分页插件
pagehelper:
diff --git a/epmet-module/epmet-third/epmet-third-server/pom.xml b/epmet-module/epmet-third/epmet-third-server/pom.xml
index 4be475b924..5ff1ac2537 100644
--- a/epmet-module/epmet-third/epmet-third-server/pom.xml
+++ b/epmet-module/epmet-third/epmet-third-server/pom.xml
@@ -197,6 +197,8 @@
false
+
+ true
false
@@ -236,6 +238,8 @@
false
+
+ false
false
@@ -274,6 +278,8 @@
false
+
+ true
true
@@ -313,6 +319,8 @@
false
+
+ false
true
diff --git a/epmet-module/epmet-third/epmet-third-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/epmet-third/epmet-third-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/epmet-third/epmet-third-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/epmet-third/epmet-third-server/src/main/resources/bootstrap.yml b/epmet-module/epmet-third/epmet-third-server/src/main/resources/bootstrap.yml
index 70ea9ad34a..0dc793c264 100644
--- a/epmet-module/epmet-third/epmet-third-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/epmet-third/epmet-third-server/src/main/resources/bootstrap.yml
@@ -35,6 +35,8 @@ spring:
namespace: @nacos.discovery.namespace@
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/gov-access/gov-access-server/pom.xml b/epmet-module/gov-access/gov-access-server/pom.xml
index 7e565cde65..859391d4bb 100644
--- a/epmet-module/gov-access/gov-access-server/pom.xml
+++ b/epmet-module/gov-access/gov-access-server/pom.xml
@@ -124,6 +124,8 @@
false
+
+ true
false
@@ -161,6 +163,8 @@
false
+
+ false
false
@@ -198,6 +202,8 @@
false
+
+ true
true
@@ -232,6 +238,8 @@
false
+
+ false
true
diff --git a/epmet-module/gov-access/gov-access-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/gov-access/gov-access-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/gov-access/gov-access-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/gov-access/gov-access-server/src/main/resources/bootstrap.yml b/epmet-module/gov-access/gov-access-server/src/main/resources/bootstrap.yml
index 978f85db31..0531e3885e 100644
--- a/epmet-module/gov-access/gov-access-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/gov-access/gov-access-server/src/main/resources/bootstrap.yml
@@ -37,6 +37,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/gov-grid/gov-grid-server/pom.xml b/epmet-module/gov-grid/gov-grid-server/pom.xml
index ec91595c79..05b5055b41 100644
--- a/epmet-module/gov-grid/gov-grid-server/pom.xml
+++ b/epmet-module/gov-grid/gov-grid-server/pom.xml
@@ -116,6 +116,8 @@
false
+
+ true
false
@@ -148,6 +150,8 @@
false
+
+ false
false
@@ -180,6 +184,8 @@
false
+
+ true
true
@@ -212,6 +218,8 @@
false
+
+ false
true
diff --git a/epmet-module/gov-grid/gov-grid-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/gov-grid/gov-grid-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/gov-grid/gov-grid-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/gov-grid/gov-grid-server/src/main/resources/bootstrap.yml b/epmet-module/gov-grid/gov-grid-server/src/main/resources/bootstrap.yml
index 4afc1b94e4..d9f0085bd7 100644
--- a/epmet-module/gov-grid/gov-grid-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/gov-grid/gov-grid-server/src/main/resources/bootstrap.yml
@@ -33,6 +33,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/gov-issue/gov-issue-server/pom.xml b/epmet-module/gov-issue/gov-issue-server/pom.xml
index 7cd3e25cf8..9019b1cda2 100644
--- a/epmet-module/gov-issue/gov-issue-server/pom.xml
+++ b/epmet-module/gov-issue/gov-issue-server/pom.xml
@@ -166,6 +166,8 @@
false
+
+ true
false
https://epmet-dev.elinkservice.cn/api/epmetscan/api
@@ -207,6 +209,8 @@
false
+
+ false
false
https://epmet-dev.elinkservice.cn/api/epmetscan/api
@@ -248,6 +252,8 @@
false
+
+ true
true
https://epmet-dev.elinkservice.cn/api/epmetscan/api
@@ -285,6 +291,8 @@
false
+
+ false
true
https://epmet-open.elinkservice.cn/api/epmetscan/api
diff --git a/epmet-module/gov-issue/gov-issue-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/gov-issue/gov-issue-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/gov-issue/gov-issue-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/gov-issue/gov-issue-server/src/main/resources/bootstrap.yml b/epmet-module/gov-issue/gov-issue-server/src/main/resources/bootstrap.yml
index 09823befef..b69f6ceec2 100644
--- a/epmet-module/gov-issue/gov-issue-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/gov-issue/gov-issue-server/src/main/resources/bootstrap.yml
@@ -37,6 +37,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/gov-mine/gov-mine-server/pom.xml b/epmet-module/gov-mine/gov-mine-server/pom.xml
index 5790de3019..2286c2c7ab 100644
--- a/epmet-module/gov-mine/gov-mine-server/pom.xml
+++ b/epmet-module/gov-mine/gov-mine-server/pom.xml
@@ -136,6 +136,9 @@
false
+
+ true
+
https://oapi.dingtalk.com/robot/send?access_token=e894e5690f9d6a527722974c71548ff6c0fe29bd956589a09e21b16442a35ed4
@@ -166,6 +169,9 @@
false
+
+ false
+
https://oapi.dingtalk.com/robot/send?access_token=e894e5690f9d6a527722974c71548ff6c0fe29bd956589a09e21b16442a35ed4
@@ -196,6 +202,9 @@
false
+
+ true
+
https://oapi.dingtalk.com/robot/send?access_token=e894e5690f9d6a527722974c71548ff6c0fe29bd956589a09e21b16442a35ed4
@@ -223,6 +232,8 @@
false
+
+ false
diff --git a/epmet-module/gov-mine/gov-mine-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/gov-mine/gov-mine-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/gov-mine/gov-mine-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/gov-mine/gov-mine-server/src/main/resources/bootstrap.yml b/epmet-module/gov-mine/gov-mine-server/src/main/resources/bootstrap.yml
index 1cfa2f121e..97052173b9 100644
--- a/epmet-module/gov-mine/gov-mine-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/gov-mine/gov-mine-server/src/main/resources/bootstrap.yml
@@ -30,6 +30,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/gov-org/gov-org-server/pom.xml b/epmet-module/gov-org/gov-org-server/pom.xml
index cc49b24887..d711c128c9 100644
--- a/epmet-module/gov-org/gov-org-server/pom.xml
+++ b/epmet-module/gov-org/gov-org-server/pom.xml
@@ -160,6 +160,8 @@
false
+
+ true
false
@@ -203,6 +205,8 @@
false
+
+ false
false
@@ -246,6 +250,8 @@
false
+
+ true
true
@@ -287,6 +293,8 @@
false
+
+ false
true
diff --git a/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/gov-org/gov-org-server/src/main/resources/bootstrap.yml b/epmet-module/gov-org/gov-org-server/src/main/resources/bootstrap.yml
index 324ed0a5ca..dc1c51b285 100644
--- a/epmet-module/gov-org/gov-org-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/gov-org/gov-org-server/src/main/resources/bootstrap.yml
@@ -70,6 +70,9 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ # 是否开启服务实例列表变更监听
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/gov-project/gov-project-server/pom.xml b/epmet-module/gov-project/gov-project-server/pom.xml
index eba323c44f..fd6f066229 100644
--- a/epmet-module/gov-project/gov-project-server/pom.xml
+++ b/epmet-module/gov-project/gov-project-server/pom.xml
@@ -165,6 +165,8 @@
false
+
+ true
false
https://epmet-dev.elinkservice.cn/api/epmetscan/api
@@ -205,6 +207,8 @@
false
+
+ false
false
https://epmet-dev.elinkservice.cn/api/epmetscan/api
@@ -244,6 +248,8 @@
false
+
+ true
true
https://epmet-dev.elinkservice.cn/api/epmetscan/api
@@ -280,6 +286,8 @@
false
+
+ false
true
https://epmet-open.elinkservice.cn/api/epmetscan/api
diff --git a/epmet-module/gov-project/gov-project-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/gov-project/gov-project-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/gov-project/gov-project-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/gov-project/gov-project-server/src/main/resources/bootstrap.yml b/epmet-module/gov-project/gov-project-server/src/main/resources/bootstrap.yml
index 74f392af96..0e8f0ca47c 100644
--- a/epmet-module/gov-project/gov-project-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/gov-project/gov-project-server/src/main/resources/bootstrap.yml
@@ -46,6 +46,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/gov-voice/gov-voice-server/pom.xml b/epmet-module/gov-voice/gov-voice-server/pom.xml
index 42be39b2e4..1e96d73266 100644
--- a/epmet-module/gov-voice/gov-voice-server/pom.xml
+++ b/epmet-module/gov-voice/gov-voice-server/pom.xml
@@ -129,6 +129,8 @@
false
+
+ true
false
https://epmet-dev.elinkservice.cn/api/epmetscan/api
@@ -168,6 +170,8 @@
false
+
+ false
false
https://epmet-dev.elinkservice.cn/api/epmetscan/api
@@ -207,6 +211,8 @@
false
+
+ true
true
https://epmet-dev.elinkservice.cn/api/epmetscan/api
@@ -243,6 +249,8 @@
false
+
+ false
true
https://epmet-open.elinkservice.cn/api/epmetscan/api
diff --git a/epmet-module/gov-voice/gov-voice-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/gov-voice/gov-voice-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/gov-voice/gov-voice-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/gov-voice/gov-voice-server/src/main/resources/bootstrap.yml b/epmet-module/gov-voice/gov-voice-server/src/main/resources/bootstrap.yml
index 8b8c4bdb45..16425361b7 100644
--- a/epmet-module/gov-voice/gov-voice-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/gov-voice/gov-voice-server/src/main/resources/bootstrap.yml
@@ -46,6 +46,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/oper-access/oper-access-server/pom.xml b/epmet-module/oper-access/oper-access-server/pom.xml
index faf1e56bbf..837011fc49 100644
--- a/epmet-module/oper-access/oper-access-server/pom.xml
+++ b/epmet-module/oper-access/oper-access-server/pom.xml
@@ -117,6 +117,8 @@
false
+
+ true
false
@@ -155,6 +157,8 @@
false
+
+ false
false
@@ -193,6 +197,8 @@
false
+
+ true
true
@@ -228,6 +234,8 @@
false
+
+ false
true
diff --git a/epmet-module/oper-access/oper-access-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/oper-access/oper-access-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/oper-access/oper-access-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/oper-access/oper-access-server/src/main/resources/bootstrap.yml b/epmet-module/oper-access/oper-access-server/src/main/resources/bootstrap.yml
index f7bad85d13..ba387b80c4 100644
--- a/epmet-module/oper-access/oper-access-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/oper-access/oper-access-server/src/main/resources/bootstrap.yml
@@ -49,6 +49,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/oper-crm/oper-crm-server/pom.xml b/epmet-module/oper-crm/oper-crm-server/pom.xml
index c9d9e19e4e..6d7a02d971 100644
--- a/epmet-module/oper-crm/oper-crm-server/pom.xml
+++ b/epmet-module/oper-crm/oper-crm-server/pom.xml
@@ -162,6 +162,8 @@
false
+
+ true
false
@@ -200,6 +202,8 @@
false
+
+ false
false
@@ -238,6 +242,8 @@
false
+
+ true
true
@@ -276,6 +282,8 @@
false
+
+ false
true
diff --git a/epmet-module/oper-crm/oper-crm-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/oper-crm/oper-crm-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/oper-crm/oper-crm-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/oper-crm/oper-crm-server/src/main/resources/bootstrap.yml b/epmet-module/oper-crm/oper-crm-server/src/main/resources/bootstrap.yml
index 3d0b42162e..dc81eba455 100644
--- a/epmet-module/oper-crm/oper-crm-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/oper-crm/oper-crm-server/src/main/resources/bootstrap.yml
@@ -49,6 +49,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/oper-customize/oper-customize-server/pom.xml b/epmet-module/oper-customize/oper-customize-server/pom.xml
index 3ca03f0165..79cc64009c 100644
--- a/epmet-module/oper-customize/oper-customize-server/pom.xml
+++ b/epmet-module/oper-customize/oper-customize-server/pom.xml
@@ -134,6 +134,8 @@
false
+
+ true
false
@@ -177,6 +179,8 @@
false
+
+ false
false
@@ -220,6 +224,8 @@
false
+
+ true
true
@@ -260,6 +266,8 @@
false
+
+ false
true
diff --git a/epmet-module/oper-customize/oper-customize-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/oper-customize/oper-customize-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/oper-customize/oper-customize-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/oper-customize/oper-customize-server/src/main/resources/bootstrap.yml b/epmet-module/oper-customize/oper-customize-server/src/main/resources/bootstrap.yml
index 3cb91d990b..c5dec6d251 100644
--- a/epmet-module/oper-customize/oper-customize-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/oper-customize/oper-customize-server/src/main/resources/bootstrap.yml
@@ -49,6 +49,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/resi-group/resi-group-server/pom.xml b/epmet-module/resi-group/resi-group-server/pom.xml
index 2eb92fdd4c..139b12d11d 100644
--- a/epmet-module/resi-group/resi-group-server/pom.xml
+++ b/epmet-module/resi-group/resi-group-server/pom.xml
@@ -181,6 +181,8 @@
false
+
+ true
false
@@ -238,6 +240,8 @@
false
+
+ false
false
@@ -293,6 +297,9 @@
false
+
+ true
+
true
@@ -345,6 +352,10 @@
false
+
+
+ false
+
true
diff --git a/epmet-module/resi-group/resi-group-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/resi-group/resi-group-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/resi-group/resi-group-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/resi-group/resi-group-server/src/main/resources/bootstrap.yml b/epmet-module/resi-group/resi-group-server/src/main/resources/bootstrap.yml
index b40b72b999..d5bdbb2300 100644
--- a/epmet-module/resi-group/resi-group-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/resi-group/resi-group-server/src/main/resources/bootstrap.yml
@@ -49,6 +49,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/resi-guide/resi-guide-server/pom.xml b/epmet-module/resi-guide/resi-guide-server/pom.xml
index 283e824c72..9cbb5ae815 100644
--- a/epmet-module/resi-guide/resi-guide-server/pom.xml
+++ b/epmet-module/resi-guide/resi-guide-server/pom.xml
@@ -138,6 +138,8 @@
false
+
+ true
false
@@ -176,6 +178,8 @@
false
+
+ false
false
@@ -214,6 +218,8 @@
false
+
+ true
true
@@ -250,6 +256,9 @@
false
+
+ false
+
true
diff --git a/epmet-module/resi-guide/resi-guide-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/resi-guide/resi-guide-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/resi-guide/resi-guide-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/resi-guide/resi-guide-server/src/main/resources/bootstrap.yml b/epmet-module/resi-guide/resi-guide-server/src/main/resources/bootstrap.yml
index a8a75e8d97..8084eeeec5 100644
--- a/epmet-module/resi-guide/resi-guide-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/resi-guide/resi-guide-server/src/main/resources/bootstrap.yml
@@ -50,6 +50,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/resi-hall/resi-hall-server/pom.xml b/epmet-module/resi-hall/resi-hall-server/pom.xml
index 0141b2e9fb..60dafe64bf 100644
--- a/epmet-module/resi-hall/resi-hall-server/pom.xml
+++ b/epmet-module/resi-hall/resi-hall-server/pom.xml
@@ -102,6 +102,8 @@
false
+
+ true
false
@@ -134,6 +136,8 @@
false
+
+ false
false
@@ -166,6 +170,8 @@
false
+
+ true
true
@@ -195,6 +201,8 @@
false
+
+ false
true
diff --git a/epmet-module/resi-hall/resi-hall-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/resi-hall/resi-hall-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/resi-hall/resi-hall-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/resi-hall/resi-hall-server/src/main/resources/bootstrap.yml b/epmet-module/resi-hall/resi-hall-server/src/main/resources/bootstrap.yml
index 19a4ef53b8..4522364f57 100644
--- a/epmet-module/resi-hall/resi-hall-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/resi-hall/resi-hall-server/src/main/resources/bootstrap.yml
@@ -33,6 +33,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/resi-home/resi-home-server/pom.xml b/epmet-module/resi-home/resi-home-server/pom.xml
index 183f71c237..12c07e44f9 100644
--- a/epmet-module/resi-home/resi-home-server/pom.xml
+++ b/epmet-module/resi-home/resi-home-server/pom.xml
@@ -126,6 +126,9 @@
false
+
+ true
+
https://oapi.dingtalk.com/robot/send?access_token=e894e5690f9d6a527722974c71548ff6c0fe29bd956589a09e21b16442a35ed4
@@ -156,6 +159,9 @@
false
+
+ false
+
https://oapi.dingtalk.com/robot/send?access_token=e894e5690f9d6a527722974c71548ff6c0fe29bd956589a09e21b16442a35ed4
@@ -186,6 +192,9 @@
false
+
+ true
+
https://oapi.dingtalk.com/robot/send?access_token=e894e5690f9d6a527722974c71548ff6c0fe29bd956589a09e21b16442a35ed4
@@ -213,6 +222,10 @@
false
+
+
+ false
+
https://oapi.dingtalk.com/robot/send?access_token=a5f66c3374b1642fe2142dbf56d5997e280172d4e8f2b546c9423a68c82ece6c
diff --git a/epmet-module/resi-home/resi-home-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/resi-home/resi-home-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/resi-home/resi-home-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/resi-home/resi-home-server/src/main/resources/bootstrap.yml b/epmet-module/resi-home/resi-home-server/src/main/resources/bootstrap.yml
index 72ede48632..b0ecb87085 100644
--- a/epmet-module/resi-home/resi-home-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/resi-home/resi-home-server/src/main/resources/bootstrap.yml
@@ -33,6 +33,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/resi-mine/resi-mine-server/pom.xml b/epmet-module/resi-mine/resi-mine-server/pom.xml
index cb66a7dd70..4f428bff56 100644
--- a/epmet-module/resi-mine/resi-mine-server/pom.xml
+++ b/epmet-module/resi-mine/resi-mine-server/pom.xml
@@ -145,6 +145,9 @@
false
+
+ true
+
https://oapi.dingtalk.com/robot/send?access_token=e894e5690f9d6a527722974c71548ff6c0fe29bd956589a09e21b16442a35ed4
@@ -174,6 +177,9 @@
false
+
+ false
+
https://oapi.dingtalk.com/robot/send?access_token=e894e5690f9d6a527722974c71548ff6c0fe29bd956589a09e21b16442a35ed4
@@ -203,6 +209,9 @@
false
+
+ true
+
https://oapi.dingtalk.com/robot/send?access_token=e894e5690f9d6a527722974c71548ff6c0fe29bd956589a09e21b16442a35ed4
@@ -229,6 +238,10 @@
false
+
+
+ false
+
https://oapi.dingtalk.com/robot/send?access_token=a5f66c3374b1642fe2142dbf56d5997e280172d4e8f2b546c9423a68c82ece6c
diff --git a/epmet-module/resi-mine/resi-mine-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/resi-mine/resi-mine-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/resi-mine/resi-mine-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/resi-mine/resi-mine-server/src/main/resources/bootstrap.yml b/epmet-module/resi-mine/resi-mine-server/src/main/resources/bootstrap.yml
index 7257f2ea6f..68fb8924c1 100644
--- a/epmet-module/resi-mine/resi-mine-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/resi-mine/resi-mine-server/src/main/resources/bootstrap.yml
@@ -33,6 +33,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/resi-partymember/resi-partymember-server/pom.xml b/epmet-module/resi-partymember/resi-partymember-server/pom.xml
index 6bad02c5e9..57a0499fd2 100644
--- a/epmet-module/resi-partymember/resi-partymember-server/pom.xml
+++ b/epmet-module/resi-partymember/resi-partymember-server/pom.xml
@@ -144,6 +144,8 @@
false
+
+ true
false
@@ -183,6 +185,8 @@
false
+
+ false
false
@@ -222,6 +226,8 @@
false
+
+ true
true
@@ -259,6 +265,9 @@
false
+
+ false
+
true
diff --git a/epmet-module/resi-partymember/resi-partymember-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/resi-partymember/resi-partymember-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/resi-partymember/resi-partymember-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/resi-partymember/resi-partymember-server/src/main/resources/bootstrap.yml b/epmet-module/resi-partymember/resi-partymember-server/src/main/resources/bootstrap.yml
index 0978c177e1..211b221914 100644
--- a/epmet-module/resi-partymember/resi-partymember-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/resi-partymember/resi-partymember-server/src/main/resources/bootstrap.yml
@@ -49,6 +49,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/resi-voice/resi-voice-server/pom.xml b/epmet-module/resi-voice/resi-voice-server/pom.xml
index 2d85b429f3..212683a9c6 100644
--- a/epmet-module/resi-voice/resi-voice-server/pom.xml
+++ b/epmet-module/resi-voice/resi-voice-server/pom.xml
@@ -102,6 +102,9 @@
false
+
+ true
+
@@ -133,6 +136,8 @@
false
+
+ false
@@ -164,6 +169,8 @@
false
+
+ true
@@ -196,6 +203,9 @@
false
+
+ false
+
diff --git a/epmet-module/resi-voice/resi-voice-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-module/resi-voice/resi-voice-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-module/resi-voice/resi-voice-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-module/resi-voice/resi-voice-server/src/main/resources/bootstrap.yml b/epmet-module/resi-voice/resi-voice-server/src/main/resources/bootstrap.yml
index 9d398946ba..156a3bf5d7 100644
--- a/epmet-module/resi-voice/resi-voice-server/src/main/resources/bootstrap.yml
+++ b/epmet-module/resi-voice/resi-voice-server/src/main/resources/bootstrap.yml
@@ -30,6 +30,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-openapi/epmet-openapi-scan/pom.xml b/epmet-openapi/epmet-openapi-scan/pom.xml
index 3cabaa5512..f3994e735f 100644
--- a/epmet-openapi/epmet-openapi-scan/pom.xml
+++ b/epmet-openapi/epmet-openapi-scan/pom.xml
@@ -104,6 +104,9 @@
false
+
+ true
+
https://oapi.dingtalk.com/robot/send?access_token=e894e5690f9d6a527722974c71548ff6c0fe29bd956589a09e21b16442a35ed4
@@ -119,7 +122,7 @@
8107
- dev
+ local
@@ -135,6 +138,10 @@
false
+
+
+ false
+
https://oapi.dingtalk.com/robot/send?access_token=e894e5690f9d6a527722974c71548ff6c0fe29bd956589a09e21b16442a35ed4
@@ -162,6 +169,9 @@
false
+
+ true
+
https://oapi.dingtalk.com/robot/send?access_token=e894e5690f9d6a527722974c71548ff6c0fe29bd956589a09e21b16442a35ed4
@@ -194,6 +204,9 @@
false
+
+ false
+
diff --git a/epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/config/NacosServiceListListenerRegisterer.java b/epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..d372fca779
--- /dev/null
+++ b/epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/config/NacosServiceListListenerRegisterer.java
@@ -0,0 +1,161 @@
+package com.epmet.openapi.scan.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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-openapi/epmet-openapi-scan/src/main/resources/bootstrap.yml b/epmet-openapi/epmet-openapi-scan/src/main/resources/bootstrap.yml
index 0aa0583c97..07a611bc39 100644
--- a/epmet-openapi/epmet-openapi-scan/src/main/resources/bootstrap.yml
+++ b/epmet-openapi/epmet-openapi-scan/src/main/resources/bootstrap.yml
@@ -33,6 +33,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-user/epmet-user-server/pom.xml b/epmet-user/epmet-user-server/pom.xml
index d1b72fa977..77cce8be87 100644
--- a/epmet-user/epmet-user-server/pom.xml
+++ b/epmet-user/epmet-user-server/pom.xml
@@ -171,6 +171,8 @@
false
+
+ true
false
https://epmet-dev.elinkservice.cn/api/epmetscan/api
@@ -210,6 +212,8 @@
false
+
+ false
false
https://epmet-dev.elinkservice.cn/api/epmetscan/api
@@ -250,6 +254,8 @@
false
+
+ true
true
https://epmet-dev.elinkservice.cn/api/epmetscan/api
@@ -287,6 +293,9 @@
false
+
+ false
+
true
https://epmet-open.elinkservice.cn/api/epmetscan/api
diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
new file mode 100644
index 0000000000..7d9a1fef05
--- /dev/null
+++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
@@ -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 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 serviceListView = null;
+ try {
+ serviceListView = namingService.getServicesOfServer(1, 100);
+ //启动监听
+ if (serviceListView == null || serviceListView.getCount() == 0) {
+ log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
+ return;
+ }
+ List 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();
+ }
+ }
+ }
+
+}
diff --git a/epmet-user/epmet-user-server/src/main/resources/bootstrap.yml b/epmet-user/epmet-user-server/src/main/resources/bootstrap.yml
index 667b9ba7c2..a3e65ad17c 100644
--- a/epmet-user/epmet-user-server/src/main/resources/bootstrap.yml
+++ b/epmet-user/epmet-user-server/src/main/resources/bootstrap.yml
@@ -70,6 +70,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@