diff --git a/epmet-admin/epmet-admin-server/pom.xml b/epmet-admin/epmet-admin-server/pom.xml
index 1bd83b7e49..fb865ce300 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
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 08b0f4b480..cb02025cdd 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
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 1e9334b0b0..4d9488dbf5 100644
--- a/epmet-gateway/pom.xml
+++ b/epmet-gateway/pom.xml
@@ -133,6 +133,9 @@
false
+
+ true
+
@@ -261,6 +264,9 @@
false
+
+
+ false
@@ -392,6 +398,9 @@
false
+
+ true
+
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 4f65034c7d..ada974c6d0 100644
--- a/epmet-gateway/src/main/resources/bootstrap.yml
+++ b/epmet-gateway/src/main/resources/bootstrap.yml
@@ -350,6 +350,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-aggregator/data-aggregator-server/pom.xml b/epmet-module/data-aggregator/data-aggregator-server/pom.xml
index a08ce28aea..a34d6056d7 100644
--- a/epmet-module/data-aggregator/data-aggregator-server/pom.xml
+++ b/epmet-module/data-aggregator/data-aggregator-server/pom.xml
@@ -214,6 +214,8 @@
false
+
+ true
false
@@ -321,6 +323,8 @@
false
+
+ false
false
@@ -428,6 +432,8 @@
false
+
+ true
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 f84136b69a..dee8b238e2 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 f1ab408d0a..185b224577 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
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 97f6c5eb85..dba76e743a 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
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..4e13474a61 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
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 204c98cfb0..06a966a303 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
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 dd2c955279..faf7cb0922 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
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 2be2091ca1..a4afdcc2ba 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
+
+ true
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 725a7342eb..1731ac910a 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
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 aa0d5545ed..97a801f969 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 6cf052999a..5c9768296a 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
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 e3178a703e..3a0f9cd454 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
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 f4349548e3..5ed97c9bd5 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
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
index c971d433b3..7d9a1fef05 100644
--- 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
@@ -28,7 +28,7 @@ import java.util.concurrent.*;
*/
@Slf4j
@Configuration
-@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceInstanceChangedListening", name = "enable", havingValue = "true", matchIfMissing = false)
+@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";
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 5d7f995e2c..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
@@ -38,8 +38,8 @@ spring:
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
# 是否开启服务实例列表变更监听
- serviceInstanceChangedListening:
- enable: true
+ serviceListChangedListening:
+ enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
diff --git a/epmet-module/epmet-third/epmet-third-server/pom.xml b/epmet-module/epmet-third/epmet-third-server/pom.xml
index a945beb046..6090c1a743 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
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 909b706005..299c03e7ac 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
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 ad73cacdaa..c4c7c2146b 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
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 04eb309484..f25c9fea6a 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
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 325ef169c4..0f5266756d 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
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 180922a33d..c0b1e136a9 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
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
index c971d433b3..7d9a1fef05 100644
--- 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
@@ -28,7 +28,7 @@ import java.util.concurrent.*;
*/
@Slf4j
@Configuration
-@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceInstanceChangedListening", name = "enable", havingValue = "true", matchIfMissing = false)
+@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";
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 e9c39f02c2..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
@@ -71,8 +71,8 @@ spring:
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
# 是否开启服务实例列表变更监听
- serviceInstanceChangedListening:
- enable: true
+ 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 4b1b8389fc..ba501c15bf 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
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 8494159692..3435fb2bfb 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
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 3fd8e4ff1c..b2f3970b1d 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
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 ee643299c2..7bf8e220de 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
+
+ true
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 13ac2c8615..d9c5b09428 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
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 494b7edfb4..ed8dd00950 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
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 ab8cfe3179..4cf6f0f33f 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
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 f3475bf89c..a8083d10de 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
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 041357ea74..346bd03c0d 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
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 3c90bc99a7..3dc61e993e 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
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 dcd85a76ce..0921d16762 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
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 3ec248aebc..6822371e16 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
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 f8641772b6..77d83cbc7d 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
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 0139688d8e..281e8b3efe 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
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@