Browse Source

Merge remote-tracking branch 'remotes/origin/develop' into release_temp

dev_shibei_match
jianjun 4 years ago
parent
commit
fc340c1049
  1. 7
      epmet-admin/epmet-admin-server/pom.xml
  2. 161
      epmet-admin/epmet-admin-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
  3. 2
      epmet-admin/epmet-admin-server/src/main/resources/bootstrap.yml
  4. 6
      epmet-auth/pom.xml
  5. 161
      epmet-auth/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
  6. 10
      epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/dto/result/CustomerStaffInfoCacheResult.java
  7. 22
      epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/redis/RedisKeys.java
  8. 5
      epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/redis/common/bean/CustomerStaffInfoCache.java
  9. 9
      epmet-gateway/pom.xml
  10. 161
      epmet-gateway/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
  11. 2
      epmet-gateway/src/main/resources/bootstrap.yml
  12. 17
      epmet-module/data-aggregator/data-aggregator-client/src/main/java/com/epmet/dataaggre/constant/TDuckConstant.java
  13. 9
      epmet-module/data-aggregator/data-aggregator-client/src/main/java/com/epmet/dataaggre/dto/epmettduck/form/TDuckDetailFormDTO.java
  14. 7
      epmet-module/data-aggregator/data-aggregator-client/src/main/java/com/epmet/dataaggre/dto/epmettduck/form/TDuckListFormDTO.java
  15. 3
      epmet-module/data-aggregator/data-aggregator-client/src/main/java/com/epmet/dataaggre/dto/epmettduck/result/CascaderDTO.java
  16. 8
      epmet-module/data-aggregator/data-aggregator-client/src/main/java/com/epmet/dataaggre/dto/epmettduck/result/ItemResDetailConcatResultDTO.java
  17. 9
      epmet-module/data-aggregator/data-aggregator-client/src/main/java/com/epmet/dataaggre/dto/epmettduck/result/PermissionValidateResultDTO.java
  18. 19
      epmet-module/data-aggregator/data-aggregator-client/src/main/java/com/epmet/dataaggre/dto/epmettduck/result/RedPointResultDTO.java
  19. 18
      epmet-module/data-aggregator/data-aggregator-client/src/main/java/com/epmet/dataaggre/dto/epmettduck/result/TDuckListResultDTO.java
  20. 5
      epmet-module/data-aggregator/data-aggregator-client/src/main/java/com/epmet/dataaggre/dto/epmetuser/result/CustomerStaffResultDTO.java
  21. 6
      epmet-module/data-aggregator/data-aggregator-server/pom.xml
  22. 161
      epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/config/NacosServiceListListenerRegisterer.java
  23. 51
      epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/controller/EpmetTDuckController.java
  24. 1
      epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/controller/GovOrgController.java
  25. 10
      epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/dao/epmettduck/PrUserProjectDao.java
  26. 7
      epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/dao/epmettduck/PrUserProjectResultDao.java
  27. 2
      epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/dao/epmettduck/PrVistRecordDao.java
  28. 25
      epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/dao/govorg/CustomerAgencyDao.java
  29. 9
      epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/QuestionnaireService.java
  30. 19
      epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/epmettduck/PrPublishRangeService.java
  31. 20
      epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/epmettduck/PrUserProjectService.java
  32. 9
      epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/epmettduck/PrVistRecordService.java
  33. 33
      epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/epmettduck/impl/PrPublishRangeServiceImpl.java
  34. 232
      epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/epmettduck/impl/PrUserProjectServiceImpl.java
  35. 22
      epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/epmettduck/impl/PrVistRecordServiceImpl.java
  36. 1
      epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/epmetuser/impl/EpmetUserServiceImpl.java
  37. 9
      epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/govorg/GovOrgService.java
  38. 18
      epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/govorg/impl/GovOrgServiceImpl.java
  39. 193
      epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/impl/QuestionnaireServiceImpl.java
  40. 2
      epmet-module/data-aggregator/data-aggregator-server/src/main/resources/bootstrap.yml
  41. 23
      epmet-module/data-aggregator/data-aggregator-server/src/main/resources/mapper/epmettduck/PrUserProjectDao.xml
  42. 5
      epmet-module/data-aggregator/data-aggregator-server/src/main/resources/mapper/epmettduck/PrUserProjectResultDao.xml
  43. 6
      epmet-module/data-aggregator/data-aggregator-server/src/main/resources/mapper/epmettduck/PrVistRecordDao.xml
  44. 27
      epmet-module/data-aggregator/data-aggregator-server/src/main/resources/mapper/govorg/CustomerAgencyDao.xml
  45. 6
      epmet-module/data-report/data-report-server/pom.xml
  46. 161
      epmet-module/data-report/data-report-server/src/main/java/com/epmet/datareport/config/NacosServiceListListenerRegisterer.java
  47. 2
      epmet-module/data-report/data-report-server/src/main/resources/bootstrap.yml
  48. 6
      epmet-module/data-statistical/data-statistical-server/pom.xml
  49. 161
      epmet-module/data-statistical/data-statistical-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
  50. 7
      epmet-module/data-statistical/data-statistical-server/src/main/java/com/epmet/dao/stats/FactPartyMemberVanguardAgencyDailyDao.java
  51. 5
      epmet-module/data-statistical/data-statistical-server/src/main/java/com/epmet/dao/stats/FactPartyMemberVanguardGridDailyDao.java
  52. 37
      epmet-module/data-statistical/data-statistical-server/src/main/java/com/epmet/service/impl/StatsPartyMemberVanguardServiceImpl.java
  53. 5
      epmet-module/data-statistical/data-statistical-server/src/main/java/com/epmet/service/stats/FactPartyMemberVanguardAgencyDailyService.java
  54. 5
      epmet-module/data-statistical/data-statistical-server/src/main/java/com/epmet/service/stats/FactPartyMemberVanguardGridDailyService.java
  55. 7
      epmet-module/data-statistical/data-statistical-server/src/main/java/com/epmet/service/stats/impl/FactPartyMemberVanguardAgencyDailyServiceImpl.java
  56. 7
      epmet-module/data-statistical/data-statistical-server/src/main/java/com/epmet/service/stats/impl/FactPartyMemberVanguardGridDailyServiceImpl.java
  57. 2
      epmet-module/data-statistical/data-statistical-server/src/main/resources/bootstrap.yml
  58. 3
      epmet-module/data-statistical/data-statistical-server/src/main/resources/mapper/stats/FactPartyMemberVanguardAgencyDailyDao.xml
  59. 3
      epmet-module/data-statistical/data-statistical-server/src/main/resources/mapper/stats/FactPartyMemberVanguardGridDailyDao.xml
  60. 6
      epmet-module/epmet-activiti/epmet-activiti-server/pom.xml
  61. 2
      epmet-module/epmet-activiti/epmet-activiti-server/src/main/resources/bootstrap.yml
  62. 6
      epmet-module/epmet-common-service/common-service-server/pom.xml
  63. 161
      epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
  64. 2
      epmet-module/epmet-common-service/common-service-server/src/main/resources/bootstrap.yml
  65. 7
      epmet-module/epmet-demo/epmet-demo-server/pom.xml
  66. 161
      epmet-module/epmet-demo/epmet-demo-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
  67. 2
      epmet-module/epmet-demo/epmet-demo-server/src/main/resources/bootstrap.yml
  68. 6
      epmet-module/epmet-ext/epmet-ext-server/pom.xml
  69. 161
      epmet-module/epmet-ext/epmet-ext-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
  70. 2
      epmet-module/epmet-ext/epmet-ext-server/src/main/resources/bootstrap.yml
  71. 8
      epmet-module/epmet-heart/epmet-heart-server/pom.xml
  72. 161
      epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
  73. 2
      epmet-module/epmet-heart/epmet-heart-server/src/main/resources/bootstrap.yml
  74. 6
      epmet-module/epmet-job/epmet-job-server/pom.xml
  75. 161
      epmet-module/epmet-job/epmet-job-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
  76. 2
      epmet-module/epmet-job/epmet-job-server/src/main/resources/bootstrap.yml
  77. 6
      epmet-module/epmet-message/epmet-message-server/pom.xml
  78. 161
      epmet-module/epmet-message/epmet-message-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
  79. 2
      epmet-module/epmet-message/epmet-message-server/src/main/resources/bootstrap.yml
  80. 6
      epmet-module/epmet-oss/epmet-oss-server/pom.xml
  81. 161
      epmet-module/epmet-oss/epmet-oss-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
  82. 2
      epmet-module/epmet-oss/epmet-oss-server/src/main/resources/bootstrap.yml
  83. 6
      epmet-module/epmet-point/epmet-point-server/pom.xml
  84. 161
      epmet-module/epmet-point/epmet-point-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
  85. 4
      epmet-module/epmet-point/epmet-point-server/src/main/resources/bootstrap.yml
  86. 6
      epmet-module/epmet-third/epmet-third-server/pom.xml
  87. 161
      epmet-module/epmet-third/epmet-third-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
  88. 2
      epmet-module/epmet-third/epmet-third-server/src/main/resources/bootstrap.yml
  89. 6
      epmet-module/gov-access/gov-access-server/pom.xml
  90. 161
      epmet-module/gov-access/gov-access-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
  91. 2
      epmet-module/gov-access/gov-access-server/src/main/resources/bootstrap.yml
  92. 6
      epmet-module/gov-grid/gov-grid-server/pom.xml
  93. 161
      epmet-module/gov-grid/gov-grid-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
  94. 2
      epmet-module/gov-grid/gov-grid-server/src/main/resources/bootstrap.yml
  95. 6
      epmet-module/gov-issue/gov-issue-server/pom.xml
  96. 161
      epmet-module/gov-issue/gov-issue-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
  97. 2
      epmet-module/gov-issue/gov-issue-server/src/main/resources/bootstrap.yml
  98. 9
      epmet-module/gov-mine/gov-mine-server/pom.xml
  99. 161
      epmet-module/gov-mine/gov-mine-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java
  100. 2
      epmet-module/gov-mine/gov-mine-server/src/main/resources/bootstrap.yml

7
epmet-admin/epmet-admin-server/pom.xml

@ -132,6 +132,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
@ -170,6 +172,9 @@
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>false</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
<!--rocketmq-->
@ -203,6 +208,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>true</spring.flyway.enabled>

161
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<String> observingServers = new ArrayList<>(33);
@PostConstruct
public void init() {
namingService = discoveryProperties.namingServiceInstance();
// 启动监听
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("NacosServiceListWatchingRegisterer");
return thread;
}
});
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS);
}
public class EpmetNacosServiceListListener implements Runnable {
@Override
public void run() {
doRefreshServerList();
}
/**
* @param
* @return
* @description 执行刷新
* @author wxz
* @date 2021.09.22 16:04:49
*/
private synchronized void doRefreshServerList() {
ListView<String> serviceListView = null;
try {
serviceListView = namingService.getServicesOfServer(1, 100);
//启动监听
if (serviceListView == null || serviceListView.getCount() == 0) {
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
return;
}
List<String> serviceList = serviceListView.getData();
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList);
for (String service : serviceList) {
try {
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
if (observingServers.contains(service)) {
continue;
}
namingService.subscribe(service, new EventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
NamingEvent namingEvent = (NamingEvent) event;
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances());
doRefreshServerList(service);
}
}
});
// 将该服务加入到监听列表中
observingServers.add(service);
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace);
}
}
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace);
}
}
/**
* @param serviceName
* @return
* @description 刷新ServerList
* @author wxz
* @date 2021.09.22 09:29:16
*/
private void doRefreshServerList(String serviceName) {
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
// try {
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
// restOfInitMethod.setAccessible(true);
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
// }
//}
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
// 暂且 1 try
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
if (loadBalancer instanceof DynamicServerListLoadBalancer) {
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer;
dslb.updateListOfServers();
}
}
}
}

2
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@

6
epmet-auth/pom.xml

@ -183,6 +183,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<!--公众号配置-->
<wx.mp.configs.appId>wxcb6ce2ed0c5ae54c</wx.mp.configs.appId>
@ -238,6 +240,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>false</nacos.service-list-changed-listening.enable>
<!--公众号配置-->
<wx.mp.configs.appId>wxcb6ce2ed0c5ae54c</wx.mp.configs.appId>
@ -290,6 +294,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<!--公众号配置-->
<wx.mp.configs.appId>wxcb6ce2ed0c5ae54c</wx.mp.configs.appId>

161
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<String> observingServers = new ArrayList<>(33);
@PostConstruct
public void init() {
namingService = discoveryProperties.namingServiceInstance();
// 启动监听
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("NacosServiceListWatchingRegisterer");
return thread;
}
});
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS);
}
public class EpmetNacosServiceListListener implements Runnable {
@Override
public void run() {
doRefreshServerList();
}
/**
* @param
* @return
* @description 执行刷新
* @author wxz
* @date 2021.09.22 16:04:49
*/
private synchronized void doRefreshServerList() {
ListView<String> serviceListView = null;
try {
serviceListView = namingService.getServicesOfServer(1, 100);
//启动监听
if (serviceListView == null || serviceListView.getCount() == 0) {
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
return;
}
List<String> serviceList = serviceListView.getData();
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList);
for (String service : serviceList) {
try {
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
if (observingServers.contains(service)) {
continue;
}
namingService.subscribe(service, new EventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
NamingEvent namingEvent = (NamingEvent) event;
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances());
doRefreshServerList(service);
}
}
});
// 将该服务加入到监听列表中
observingServers.add(service);
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace);
}
}
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace);
}
}
/**
* @param serviceName
* @return
* @description 刷新ServerList
* @author wxz
* @date 2021.09.22 09:29:16
*/
private void doRefreshServerList(String serviceName) {
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
// try {
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
// restOfInitMethod.setAccessible(true);
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
// }
//}
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
// 暂且 1 try
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
if (loadBalancer instanceof DynamicServerListLoadBalancer) {
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer;
dslb.updateListOfServers();
}
}
}
}

10
epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/dto/result/CustomerStaffInfoCacheResult.java

@ -22,6 +22,11 @@ public class CustomerStaffInfoCacheResult implements Serializable {
*/
private String agencyId;
/**
* 工作人员所属组织ID的pids
*/
private String agencyPIds;
/**
* 工作人员所属组织名称
*/
@ -57,6 +62,11 @@ public class CustomerStaffInfoCacheResult implements Serializable {
*/
private String headPhoto;
/**
* 工作人员是从哪中组织添加的 组织Id
*/
private String fromOrgId;
/**
* 工作人员是从哪中组织类型添加的 3个值agencygriddept
* @see com.epmet.commons.tools.enums.OrgTypeEnum

22
epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/redis/RedisKeys.java

@ -212,6 +212,15 @@ public class RedisKeys {
return rootPrefix.concat("gov:agency:").concat(agencyId);
}
/**
* 网格信息key
* @param gridId
* @return
*/
public static String getGridByIdKey(String gridId) {
return rootPrefix.concat("gov:grid:").concat(gridId);
}
/**
* 客户标签排行 缓存Key
* @param customerId
@ -535,4 +544,17 @@ public class RedisKeys {
public static String getGridInfoKey(String gridId) {
return rootPrefix.concat("gov:grid:").concat(gridId);
}
/**
* @description 调查问卷accessKey
*
* @param userId
* @param qKey
* @return
* @author wxz
* @date 2021.09.23 17:38:37
*/
public static String getQuestionnaireAccessKey(String userId, String qKey) {
return rootPrefix.concat("questionnaire:accesskey:").concat(userId).concat(":").concat(qKey);
}
}

5
epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/redis/common/bean/CustomerStaffInfoCache.java

@ -22,6 +22,11 @@ public class CustomerStaffInfoCache implements Serializable {
*/
private String agencyId;
/**
* 工作人员所属组织ID的pids
*/
private String agencyPIds;
/**
* 工作人员所属组织名称
*/

9
epmet-gateway/pom.xml

@ -133,6 +133,9 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip></nacos.ip>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<!-- gateway routes -->
<!-- 1、认证服务 -->
<!-- <gateway.routes.epmet-auth-server.uri>http://localhost:8081</gateway.routes.epmet-auth-server.uri>-->
@ -264,6 +267,9 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip></nacos.ip>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>false</nacos.service-list-changed-listening.enable>
<!-- gateway routes -->
<!-- 1、认证服务 -->
<!-- <gateway.routes.epmet-auth-server.uri>http://localhost:8081</gateway.routes.epmet-auth-server.uri>-->
@ -398,6 +404,9 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<!-- gateway routes -->
<!-- 1、认证服务 -->
<gateway.routes.epmet-auth-server.uri>lb://epmet-auth-server</gateway.routes.epmet-auth-server.uri>

161
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<String> observingServers = new ArrayList<>(33);
@PostConstruct
public void init() {
namingService = discoveryProperties.namingServiceInstance();
// 启动监听
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("NacosServiceListWatchingRegisterer");
return thread;
}
});
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS);
}
public class EpmetNacosServiceListListener implements Runnable {
@Override
public void run() {
doRefreshServerList();
}
/**
* @param
* @return
* @description 执行刷新
* @author wxz
* @date 2021.09.22 16:04:49
*/
private synchronized void doRefreshServerList() {
ListView<String> serviceListView = null;
try {
serviceListView = namingService.getServicesOfServer(1, 100);
//启动监听
if (serviceListView == null || serviceListView.getCount() == 0) {
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
return;
}
List<String> serviceList = serviceListView.getData();
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList);
for (String service : serviceList) {
try {
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
if (observingServers.contains(service)) {
continue;
}
namingService.subscribe(service, new EventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
NamingEvent namingEvent = (NamingEvent) event;
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances());
doRefreshServerList(service);
}
}
});
// 将该服务加入到监听列表中
observingServers.add(service);
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace);
}
}
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace);
}
}
/**
* @param serviceName
* @return
* @description 刷新ServerList
* @author wxz
* @date 2021.09.22 09:29:16
*/
private void doRefreshServerList(String serviceName) {
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
// try {
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
// restOfInitMethod.setAccessible(true);
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
// }
//}
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
// 暂且 1 try
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
if (loadBalancer instanceof DynamicServerListLoadBalancer) {
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer;
dslb.updateListOfServers();
}
}
}
}

2
epmet-gateway/src/main/resources/bootstrap.yml

@ -358,6 +358,8 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
serviceListChangedListening:
enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@

17
epmet-module/data-aggregator/data-aggregator-client/src/main/java/com/epmet/dataaggre/constant/TDuckConstant.java

@ -0,0 +1,17 @@
package com.epmet.dataaggre.constant;
/**
* @Author zxc
* @DateTime 2021/9/23 4:06 下午
* @DESC
*/
public interface TDuckConstant {
String CLIENT_GOV = "gov";
String CLIENT_RESI = "resi";
String ORG_TYPE_AGENCY = "agency";
String ORG_TYPE_GRID = "grid";
String ORG_TYPE_DEPT = "dept";
}

9
epmet-module/data-aggregator/data-aggregator-client/src/main/java/com/epmet/dataaggre/dto/epmettduck/form/TDuckDetailFormDTO.java

@ -17,15 +17,22 @@ public class TDuckDetailFormDTO implements Serializable {
private static final long serialVersionUID = 3793280475377993346L;
public interface TDuckDetailForm{}
public interface PermissionValidate{}
/**
* 项目key
*/
@NotBlank(message = "项目key不能为空",groups = TDuckDetailForm.class)
@NotBlank(message = "项目key不能为空",groups = { TDuckDetailForm.class, PermissionValidate.class })
private String key;
/**
* 是否显示类型
*/
@NotNull(message = "是否显示类型不能为空",groups = TDuckDetailForm.class)
private Boolean displayType;
/** 当前操作人所在的组织的类型(grid:网格,agency:单位) */
private String orgType;
/** 当前操作人所在的组织的ID(当orgType为grid的时候必填,为agency的时候留空) */
private String orgId;
}

7
epmet-module/data-aggregator/data-aggregator-client/src/main/java/com/epmet/dataaggre/dto/epmettduck/form/TDuckListFormDTO.java

@ -30,11 +30,14 @@ public class TDuckListFormDTO implements Serializable {
@NotNull(message = "pageSize不能为空",groups = TDuckListForm.class)
private Integer pageSize;
@NotBlank(message = "orgIds不能为空",groups = TDuckListForm.class)
private String orgIds;
private String orgId;
private String orgType;
@NotBlank(message = "client不能为空",groups = TDuckListForm.class)
private String client;
private String userId;
private String customerId;
}

3
epmet-module/data-aggregator/data-aggregator-client/src/main/java/com/epmet/dataaggre/dto/epmettduck/result/CascaderDTO.java

@ -29,11 +29,12 @@ public class CascaderDTO implements Serializable {
/**
* pid
*/
private String pid;
private Integer pid;
/**
* 全路径名字
*/
private List<String> labels;
public String pathName;
}

8
epmet-module/data-aggregator/data-aggregator-client/src/main/java/com/epmet/dataaggre/dto/epmettduck/result/ItemResDetailConcatResultDTO.java

@ -5,9 +5,10 @@ import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @Description TODO
* @Description 联系人组件
* @Author yinzuomei
* @Date 2021/9/22 2:54 下午
*/
@ -15,11 +16,12 @@ import java.util.List;
public class ItemResDetailConcatResultDTO implements Serializable {
private static final long serialVersionUID = -3695200094740706700L;
private List<ConcatTableHeaderDTO> tableHeaderList;
private List<List<String>> dataList;
private List<Map<String,String>> dataMap;
//private List<List<String>> dataList;
public ItemResDetailConcatResultDTO(){
this.tableHeaderList=new ArrayList<>();
this.dataList=new ArrayList<>();
this.dataMap=new ArrayList<>();
}
}

9
epmet-module/data-aggregator/data-aggregator-client/src/main/java/com/epmet/dataaggre/dto/epmettduck/result/PermissionValidateResultDTO.java

@ -0,0 +1,9 @@
package com.epmet.dataaggre.dto.epmettduck.result;
import lombok.Data;
@Data
public class PermissionValidateResultDTO {
private Boolean permitted;
private String accessKey;
}

19
epmet-module/data-aggregator/data-aggregator-client/src/main/java/com/epmet/dataaggre/dto/epmettduck/result/RedPointResultDTO.java

@ -0,0 +1,19 @@
package com.epmet.dataaggre.dto.epmettduck.result;
import lombok.Data;
import java.io.Serializable;
/**
* @Description
* @Author zhaoqifeng
* @Date 2021/9/23 10:03
*/
@Data
public class RedPointResultDTO implements Serializable {
private static final long serialVersionUID = -2230123089546481389L;
/**
* redPoint
*/
private String redPoint;
}

18
epmet-module/data-aggregator/data-aggregator-client/src/main/java/com/epmet/dataaggre/dto/epmettduck/result/TDuckListResultDTO.java

@ -1,6 +1,7 @@
package com.epmet.dataaggre.dto.epmettduck.result;
import com.epmet.commons.tools.constant.NumConstant;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@ -74,11 +75,26 @@ public class TDuckListResultDTO implements Serializable {
*/
private Boolean fillStatus;
/**
* 是否还能填写问卷true不能false
*/
private Boolean isFillQuestion;
/**
* 回收状态 0:未回收1已回收
*/
private Integer recycled;
/**
* 组织名
*/
private String orgName;
private String createdBy;
@JsonIgnore
private Integer isEveryoneWriteOnceUid;
public TDuckListResultDTO() {
this.customerId = "";
this.key = "";
@ -92,5 +108,7 @@ public class TDuckListResultDTO implements Serializable {
this.client = "";
this.createdTime = "";
this.fillStatus = false;
this.isFillQuestion = true;
this.orgName = "";
}
}

5
epmet-module/data-aggregator/data-aggregator-client/src/main/java/com/epmet/dataaggre/dto/epmetuser/result/CustomerStaffResultDTO.java

@ -21,6 +21,11 @@ public class CustomerStaffResultDTO implements Serializable {
*/
private String agencyId;
/**
* 工作人员所属组织ID的pids
*/
private String agencyPIds;
/**
* 工作人员所属组织名称
*/

6
epmet-module/data-aggregator/data-aggregator-server/pom.xml

@ -221,6 +221,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<!--flyway migration 数据库迁移工具-->
<spring.flyway.enabled>false</spring.flyway.enabled>
@ -335,6 +337,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>false</nacos.service-list-changed-listening.enable>
<!--flyway migration 数据库迁移工具-->
<spring.flyway.enabled>false</spring.flyway.enabled>
@ -449,6 +453,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<!--flyway migration 数据库迁移工具-->
<spring.flyway.enabled>true</spring.flyway.enabled>

161
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<String> observingServers = new ArrayList<>(33);
@PostConstruct
public void init() {
namingService = discoveryProperties.namingServiceInstance();
// 启动监听
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("NacosServiceListWatchingRegisterer");
return thread;
}
});
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS);
}
public class EpmetNacosServiceListListener implements Runnable {
@Override
public void run() {
doRefreshServerList();
}
/**
* @param
* @return
* @description 执行刷新
* @author wxz
* @date 2021.09.22 16:04:49
*/
private synchronized void doRefreshServerList() {
ListView<String> serviceListView = null;
try {
serviceListView = namingService.getServicesOfServer(1, 100);
//启动监听
if (serviceListView == null || serviceListView.getCount() == 0) {
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
return;
}
List<String> serviceList = serviceListView.getData();
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList);
for (String service : serviceList) {
try {
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
if (observingServers.contains(service)) {
continue;
}
namingService.subscribe(service, new EventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
NamingEvent namingEvent = (NamingEvent) event;
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances());
doRefreshServerList(service);
}
}
});
// 将该服务加入到监听列表中
observingServers.add(service);
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace);
}
}
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace);
}
}
/**
* @param serviceName
* @return
* @description 刷新ServerList
* @author wxz
* @date 2021.09.22 09:29:16
*/
private void doRefreshServerList(String serviceName) {
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
// try {
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
// restOfInitMethod.setAccessible(true);
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
// }
//}
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
// 暂且 1 try
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
if (loadBalancer instanceof DynamicServerListLoadBalancer) {
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer;
dslb.updateListOfServers();
}
}
}
}

51
epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/controller/EpmetTDuckController.java

@ -1,6 +1,9 @@
package com.epmet.dataaggre.controller;
import com.epmet.commons.tools.annotation.LoginUser;
import com.epmet.commons.tools.constant.AppClientConstant;
import com.epmet.commons.tools.exception.EpmetErrorCode;
import com.epmet.commons.tools.exception.ValidateException;
import com.epmet.commons.tools.security.dto.TokenDto;
import com.epmet.commons.tools.utils.Result;
import com.epmet.commons.tools.validator.ValidatorUtils;
@ -9,14 +12,12 @@ import com.epmet.dataaggre.dto.epmettduck.form.*;
import com.epmet.dataaggre.dto.epmettduck.result.*;
import com.epmet.dataaggre.entity.epmettduck.PrUserProjectEntity;
import com.epmet.dataaggre.entity.epmettduck.PrUserProjectItemEntity;
import com.epmet.dataaggre.service.QuestionnaireService;
import com.epmet.dataaggre.service.epmettduck.PrUserProjectItemService;
import com.epmet.dataaggre.service.epmettduck.PrUserProjectService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
@ -31,6 +32,8 @@ public class EpmetTDuckController {
private PrUserProjectService prUserProjectService;
@Autowired
private PrUserProjectItemService projectItemService;
@Autowired
private QuestionnaireService questionnaireService;
/**
@ -81,6 +84,7 @@ public class EpmetTDuckController {
public Result<List<TDuckListResultDTO>> queryProjectList(@RequestBody TDuckListFormDTO formDTO,@LoginUser TokenDto tokenDto){
ValidatorUtils.validateEntity(formDTO,TDuckListFormDTO.TDuckListForm.class);
formDTO.setUserId(tokenDto.getUserId());
formDTO.setCustomerId(tokenDto.getCustomerId());
return new Result<List<TDuckListResultDTO>>().ok(prUserProjectService.queryProjectList(formDTO));
}
@ -137,4 +141,41 @@ public class EpmetTDuckController {
ValidatorUtils.validateEntity(formDTO,ProjectKeyCommonDTO.AddUserInternalGroup.class);
return new Result<ItemResDetailConcatResultDTO>().ok(prUserProjectService.queryItemResDetailConcat(formDTO));
}
@PostMapping("redpoint")
public Result<RedPointResultDTO> redPoint(@LoginUser TokenDto tokenDto) {
return new Result<RedPointResultDTO>().ok(prUserProjectService.redPoint(tokenDto));
}
/**
* @description 校验权限并且获取accesskey
*
* @param input
* @return
* @author wxz
* @date 2021.09.23 15:13:53
*/
@PostMapping("/permission-validate")
public Result<PermissionValidateResultDTO> permissionValidate(@RequestBody TDuckDetailFormDTO input, @LoginUser TokenDto loginUserInfo, @RequestHeader("customerId") String customerId) {
ValidatorUtils.validateEntity(input, TDuckDetailFormDTO.PermissionValidate.class);
// 所用端的类型:gov:工作端,resi居民端
String app = loginUserInfo.getApp();
String orgId = input.getOrgId();
String projectKey = input.getKey();
String userId = loginUserInfo.getUserId();
PermissionValidateResultDTO r = null;
if (AppClientConstant.APP_RESI.equals(app)) {
if (StringUtils.isBlank(orgId) || !"grid".equals(input.getOrgType())) {
// 居民端,orgId是网格id,必填
throw new ValidateException(EpmetErrorCode.INTERNAL_VALIDATE_ERROR.getCode(), "【调查问卷】校验访问权限-居民端 orgId不能为空,且orgType需要为[grid]");
}
r = questionnaireService.resiPermissionValidate(projectKey, userId, orgId);
} else if (AppClientConstant.APP_GOV.equals(app)) {
// 工作端
r = questionnaireService.govPermissionValidate(projectKey, userId, customerId);
}
return new Result<PermissionValidateResultDTO>().ok(r);
}
}

1
epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/controller/GovOrgController.java

@ -175,7 +175,6 @@ public class GovOrgController {
*/
@PostMapping("agencytree")
public Result<List<OrgTreeResultDTO>> getAgencyTree(@LoginUser TokenDto tokenDto, @RequestBody SubOrgFormDTO formDTO) {
ValidatorUtils.validateEntity(formDTO);
return new Result<List<OrgTreeResultDTO>>().ok(govOrgService.getAgencyTree(tokenDto, formDTO));
}

10
epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/dao/epmettduck/PrUserProjectDao.java

@ -55,7 +55,7 @@ public interface PrUserProjectDao extends BaseDao<PrUserProjectEntity> {
* @author zxc
* @date 2021/9/17 2:16 下午
*/
List<String> selectProjectKey(@Param("orgIds")String orgIds);
List<String> selectProjectKey(@Param("orgIds")List<String> orgIds);
/**
* @Description 根据keys查询project
@ -65,14 +65,6 @@ public interface PrUserProjectDao extends BaseDao<PrUserProjectEntity> {
*/
List<TDuckListResultDTO> queryProjectList(@Param("keys")List<String> keys, @Param("status")Integer status,@Param("client")String client);
/**
* @Description 查询头部信息问卷调查的名字和描述
* @Param key
* @author zxc
* @date 2021/9/22 9:42 上午
*/
PrUserProjectEntity selectHeaderInfoByKey(@Param("key")String key);
/**
* 当前问卷中所有的联系人组件
*

7
epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/dao/epmettduck/PrUserProjectResultDao.java

@ -3,6 +3,9 @@ package com.epmet.dataaggre.dao.epmettduck;
import com.epmet.commons.mybatis.dao.BaseDao;
import com.epmet.dataaggre.entity.epmettduck.PrUserProjectResultEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 项目表单项
@ -12,5 +15,7 @@ import org.apache.ibatis.annotations.Mapper;
*/
@Mapper
public interface PrUserProjectResultDao extends BaseDao<PrUserProjectResultEntity> {
List<String> selectFillRecordByUserId(@Param("userId")String userId);
}

2
epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/dao/epmettduck/PrVistRecordDao.java

@ -16,6 +16,6 @@ import java.util.List;
@Mapper
public interface PrVistRecordDao extends BaseDao<PrVistRecordEntity> {
List<String> selectVisitRecordByUserId(@Param("userId")String userId);
}

25
epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/dao/govorg/CustomerAgencyDao.java

@ -71,10 +71,31 @@ public interface CustomerAgencyDao extends BaseDao<CustomerAgencyEntity> {
* @return
*/
StaffOrgRelationResultDTO getStaffFromOrgType(@Param("staffId") String staffId);
/**
* @Description 工作端组织级下级组织树
* @Param agencyId
* @Return {@link OrgTreeResultDTO}
* @Author zhaoqifeng
* @Date 2021/9/23 10:16
*/
OrgTreeResultDTO getOrgTree(@Param("agencyId") String agencyId);
List<OrgTreeResultDTO> getSubOrgList(@Param("pid") String pid);
/**
* @Description 居民端组织级下级组织树
* @Param agencyId
* @Return {@link OrgTreeResultDTO}
* @Author zhaoqifeng
* @Date 2021/9/23 10:16
*/
OrgTreeResultDTO getResiOrgTree(@Param("agencyId") String agencyId);
List<OrgTreeResultDTO> getResiSubOrgList(@Param("pid") String pid);
/**
* @Description 工作人员所在的组织部门网格
* @Param staffId
* @Return {@link List< String>}
* @Author zhaoqifeng
* @Date 2021/9/23 10:16
*/
List<String> getOrgList(@Param("staffId") String staffId);
}

9
epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/QuestionnaireService.java

@ -0,0 +1,9 @@
package com.epmet.dataaggre.service;
import com.epmet.dataaggre.dto.epmettduck.result.PermissionValidateResultDTO;
public interface QuestionnaireService {
PermissionValidateResultDTO resiPermissionValidate(String projectKey, String userId, String gridId);
PermissionValidateResultDTO govPermissionValidate(String projectKey, String staffId, String customerId);
}

19
epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/epmettduck/PrPublishRangeService.java

@ -101,4 +101,23 @@ public interface PrPublishRangeService extends BaseService<PrPublishRangeEntity>
* @Date 2021/9/18 15:28
*/
List<String> getRangeOrgList(String projectKey);
/**
* @description 使用projectKey查询发布范围entity
*
* @param projectKey
* @return
* @author wxz
* @date 2021.09.23 23:04:23
*/
List<PrPublishRangeEntity> getPublishRangeEntity(String projectKey);
/**
* @Description 获取组织范围内的问卷
* @Param orgList
* @Return {@link List< PrPublishRangeDTO>}
* @Author zhaoqifeng
* @Date 2021/9/23 10:27
*/
List<PrPublishRangeDTO> getListByOrg(List<String> orgList);
}

20
epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/epmettduck/PrUserProjectService.java

@ -19,6 +19,7 @@ package com.epmet.dataaggre.service.epmettduck;
import com.epmet.commons.mybatis.service.BaseService;
import com.epmet.commons.tools.page.PageData;
import com.epmet.commons.tools.security.dto.TokenDto;
import com.epmet.dataaggre.dto.epmettduck.PrUserProjectDTO;
import com.epmet.dataaggre.dto.epmettduck.form.ItemResDetailFormDTO;
import com.epmet.dataaggre.dto.epmettduck.form.ProjectKeyCommonDTO;
@ -164,4 +165,23 @@ public interface PrUserProjectService extends BaseService<PrUserProjectEntity> {
* @date 2021/9/22 2:57 下午
*/
ItemResDetailConcatResultDTO queryItemResDetailConcat(ProjectKeyCommonDTO formDTO);
/**
* 有新的问卷显示小红点
* @Param tokenDto
* @Return {@link RedPointResultDTO}
* @Author zhaoqifeng
* @Date 2021/9/23 10:05
*/
RedPointResultDTO redPoint(TokenDto tokenDto);
/**
* @description 根据key查询问卷
*
* @param key
* @return
* @author wxz
* @date 2021.09.23 22:25:57
*/
PrUserProjectEntity getProjectEntityBykey(String key);
}

9
epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/epmettduck/PrVistRecordService.java

@ -92,4 +92,13 @@ public interface PrVistRecordService extends BaseService<PrVistRecordEntity> {
* @date 2021-09-15
*/
void delete(String[] ids);
/**
* @Description 获取最新访问记录
* @Param staffId
* @Return {@link PrVistRecordDTO}
* @Author zhaoqifeng
* @Date 2021/9/23 14:16
*/
PrVistRecordDTO getNewestRecord(String staffId);
}

33
epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/epmettduck/impl/PrPublishRangeServiceImpl.java

@ -23,6 +23,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.epmet.commons.dynamic.datasource.annotation.DataSource;
import com.epmet.commons.mybatis.service.impl.BaseServiceImpl;
import com.epmet.commons.tools.constant.FieldConstant;
import com.epmet.commons.tools.constant.NumConstant;
import com.epmet.commons.tools.page.PageData;
import com.epmet.commons.tools.utils.ConvertUtils;
import com.epmet.dataaggre.constant.DataSourceConstant;
@ -124,4 +125,36 @@ public class PrPublishRangeServiceImpl extends BaseServiceImpl<PrPublishRangeDao
return list.stream().map(PrPublishRangeEntity::getOrgId).collect(Collectors.toList());
}
@Override
public List<PrPublishRangeEntity> getPublishRangeEntity(String projectKey) {
LambdaQueryWrapper<PrPublishRangeEntity> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(PrPublishRangeEntity::getProjectKey, projectKey);
return baseDao.selectList(wrapper);
}
/**
* @param orgList
* @Description 获取组织范围内的问卷
* @Param orgList
* @Return {@link List< PrPublishRangeDTO>}
* @Author zhaoqifeng
* @Date 2021/9/23 10:27
*/
@Override
public List<PrPublishRangeDTO> getListByOrg(List<String> orgList) {
LambdaQueryWrapper<PrPublishRangeEntity> wrapper = new LambdaQueryWrapper<>();
wrapper.and(w -> {
for (int i = 0; i < orgList.size(); i++) {
if (NumConstant.ZERO == i) {
w.like(PrPublishRangeEntity :: getOrgId, orgList.get(i));
} else {
w.or().like(PrPublishRangeEntity :: getOrgId, orgList.get(i));
}
}
});
wrapper.orderByDesc(PrPublishRangeEntity::getCreatedTime);
List<PrPublishRangeEntity> list = baseDao.selectList(wrapper);
return ConvertUtils.sourceToTarget(list, PrPublishRangeDTO.class);
}
}

232
epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/epmettduck/impl/PrUserProjectServiceImpl.java

@ -27,12 +27,22 @@ import com.epmet.commons.mybatis.service.impl.BaseServiceImpl;
import com.epmet.commons.tools.constant.FieldConstant;
import com.epmet.commons.tools.constant.NumConstant;
import com.epmet.commons.tools.constant.StrConstant;
import com.epmet.commons.tools.dto.form.IdAndNameDTO;
import com.epmet.commons.tools.dto.result.CustomerStaffInfoCacheResult;
import com.epmet.commons.tools.exception.RenException;
import com.epmet.commons.tools.page.PageData;
import com.epmet.commons.tools.redis.common.CustomerStaffRedis;
import com.epmet.commons.tools.security.dto.TokenDto;
import com.epmet.commons.tools.utils.ConvertUtils;
import com.epmet.commons.tools.utils.Result;
import com.epmet.dataaggre.constant.DataSourceConstant;
import com.epmet.dataaggre.constant.TDuckConstant;
import com.epmet.dataaggre.dao.epmettduck.PrUserProjectDao;
import com.epmet.dataaggre.dao.epmettduck.PrUserProjectResultDao;
import com.epmet.dataaggre.dao.epmettduck.PrVistRecordDao;
import com.epmet.dataaggre.dto.epmettduck.PrPublishRangeDTO;
import com.epmet.dataaggre.dto.epmettduck.PrUserProjectDTO;
import com.epmet.dataaggre.dto.epmettduck.PrVistRecordDTO;
import com.epmet.dataaggre.dto.epmettduck.ProjectItemTypeEnum;
import com.epmet.dataaggre.dto.epmettduck.form.ItemResDetailFormDTO;
import com.epmet.dataaggre.dto.epmettduck.form.ProjectKeyCommonDTO;
@ -44,6 +54,11 @@ import com.epmet.dataaggre.entity.epmettduck.PrUserProjectEntity;
import com.epmet.dataaggre.entity.epmettduck.PrUserProjectResultEntity;
import com.epmet.dataaggre.service.epmettduck.PrPublishRangeService;
import com.epmet.dataaggre.service.epmettduck.PrUserProjectService;
import com.epmet.dataaggre.service.epmettduck.PrVistRecordService;
import com.epmet.dataaggre.service.govorg.GovOrgService;
import com.epmet.dto.CustomerGridDTO;
import com.epmet.dto.form.CustomerGridFormDTO;
import com.epmet.feign.GovOrgOpenFeignClient;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
@ -71,9 +86,15 @@ import java.util.stream.Stream;
public class PrUserProjectServiceImpl extends BaseServiceImpl<PrUserProjectDao, PrUserProjectEntity> implements PrUserProjectService {
@Autowired
private PrVistRecordDao visitRecordDao;
private PrUserProjectResultDao prUserProjectResultDao;
@Resource
private PrPublishRangeService prPublishRangeService;
@Resource
private GovOrgService govOrgService;
@Resource
private PrVistRecordService prVistRecordService;
@Autowired
private GovOrgOpenFeignClient govOrgOpenFeignClient;
@Override
public PageData<PrUserProjectDTO> page(Map<String, Object> params) {
@ -148,26 +169,109 @@ public class PrUserProjectServiceImpl extends BaseServiceImpl<PrUserProjectDao,
*/
@Override
public List<TDuckListResultDTO> queryProjectList(TDuckListFormDTO formDTO) {
List<String> projectKeys = baseDao.selectProjectKey(formDTO.getOrgIds());
List<String> orgIds = new ArrayList<>();
// 工作端不需要传orgId
if (formDTO.getClient().equals(TDuckConstant.CLIENT_GOV)){
// 根据 客户ID 和 人ID 从redis获取信息
CustomerStaffInfoCacheResult staffInfo = CustomerStaffRedis.getStaffInfo(formDTO.getCustomerId(), formDTO.getUserId());
String pids = staffInfo.getAgencyPIds();
String agencyId = staffInfo.getAgencyId();
// 来源于 部门
if (staffInfo.getFromOrgType().equals(TDuckConstant.ORG_TYPE_DEPT)){
List<IdAndNameDTO> deptList = staffInfo.getDeptList();
if (CollectionUtils.isEmpty(deptList)){
return new ArrayList<>();
}
orgIds = joint(pids,agencyId,deptList);
// 来源于 网格
}else if (staffInfo.getFromOrgType().equals(TDuckConstant.ORG_TYPE_GRID)){
List<IdAndNameDTO> gridList = staffInfo.getGridList();
if (CollectionUtils.isEmpty(gridList)){
return new ArrayList<>();
}
orgIds = joint(pids,agencyId,gridList);
}else {
String selfOrg = pids + ":" + agencyId;
orgIds.add(selfOrg);
}
}else {
CustomerGridFormDTO customerGridFormDTO = new CustomerGridFormDTO();
customerGridFormDTO.setGridId(formDTO.getOrgId());
// 查询网格信息
Result<CustomerGridDTO> gridResult = govOrgOpenFeignClient.getGridBaseInfoByGridId(customerGridFormDTO);
if (!gridResult.success()){
throw new RenException("查询网格信息失败了...");
}
CustomerGridDTO data = gridResult.getData();
String oneOrg = data.getPids() + ":" + data.getId();
orgIds.add(oneOrg);
}
// 根据orgIds查询 问卷调查的key
List<String> projectKeys = baseDao.selectProjectKey(orgIds);
if (CollectionUtils.isEmpty(projectKeys)){
return new ArrayList<>();
}
PageInfo<TDuckListResultDTO> projectPageInfo = PageHelper.startPage(formDTO.getPageNo(), formDTO.getPageSize()).doSelectPageInfo(() -> baseDao.queryProjectList(projectKeys, formDTO.getStatus(), formDTO.getClient()));
List<TDuckListResultDTO> result = projectPageInfo.getList();
List<String> records = visitRecordDao.selectVisitRecordByUserId(formDTO.getUserId());
// 查询此人已填写过的问卷 并赋值已填写字段
List<String> records = prUserProjectResultDao.selectFillRecordByUserId(formDTO.getUserId());
if (!CollectionUtils.isEmpty(records)){
for (String r : records) {
for (TDuckListResultDTO t : result) {
if (t.getIsEveryoneWriteOnceUid() == NumConstant.ONE && r.equals(t.getKey())){
t.setIsFillQuestion(false);
}
if (r.equals(t.getKey())){
t.setFillStatus(true);
continue;
}
}
}
}
//赋值 orgName
result.forEach(r -> {
CustomerStaffInfoCacheResult staffInfo = CustomerStaffRedis.getStaffInfo(formDTO.getCustomerId(), r.getCreatedBy());
String orgName = "";
if (null != staffInfo){
if (staffInfo.getFromOrgType().equals(TDuckConstant.ORG_TYPE_AGENCY)){
orgName = staffInfo.getAgencyName();
}else if (staffInfo.getFromOrgType().equals(TDuckConstant.ORG_TYPE_GRID)){
for (IdAndNameDTO g : staffInfo.getGridList()) {
if (g.getId().equals(staffInfo.getFromOrgId())){
orgName = g.getName();
continue;
}
}
}else if (staffInfo.getFromOrgType().equals(TDuckConstant.ORG_TYPE_DEPT)){
for (IdAndNameDTO d : staffInfo.getDeptList()) {
if (d.getId().equals(staffInfo.getFromOrgId())){
orgName = d.getName();
continue;
}
}
}
}
r.setOrgName(orgName);
});
return result;
}
/**
* @Description orgIds拼接
* @Param pids
* @Param agencyId
* @Param list
* @author zxc
* @date 2021/9/23 4:48 下午
*/
public List<String> joint(String pids, String agencyId, List<IdAndNameDTO> list){
List<String> orgIds = new ArrayList<>();
list.forEach(l -> {
String oneOrg = pids + ":" + agencyId + ":" + l.getId();
orgIds.add(oneOrg);
});
return orgIds;
}
/**
* 分析报告
*
@ -376,7 +480,8 @@ public class PrUserProjectServiceImpl extends BaseServiceImpl<PrUserProjectDao,
int totalCount = 0;
Map<String, Integer> resMap = new HashMap<>();
for (PrUserProjectResultEntity res : resultList) {
JSONObject originalData = JSON.parseObject(res.getOriginalData());
//级联组件,用processdata特殊处理下
JSONObject originalData = JSON.parseObject(res.getProcessData());
if(originalData.containsKey(key)){
List<CascaderDTO> dtoList = JSON.parseArray(originalData.get(key).toString(), CascaderDTO.class);
if(CollectionUtils.isEmpty(dtoList)){
@ -608,63 +713,100 @@ public class PrUserProjectServiceImpl extends BaseServiceImpl<PrUserProjectDao,
tableHeaderList.add(headerDTO);
}
List<List<String>> dataList=new ArrayList<>();
for(PrUserProjectResultEntity res:resultList){
List<String> userAnswer=new ArrayList<>();
JSONObject originalData = JSON.parseObject(res.getOriginalData());
for(ConcatTableHeaderDTO header:tableHeaderList){
String key="field".concat(header.getFormItemId());
List<Map<String,String>> dataMap=new ArrayList<>();
for (PrUserProjectResultEntity res : resultList) {
JSONObject originalData = JSON.parseObject(res.getOriginalData());
Map<String,String> mapUnit=new HashMap<>();
//start
for (ConcatTableHeaderDTO header : tableHeaderList) {
String key = "field".concat(header.getFormItemId());
//手机号、邮箱、身份证、单行文本: INPUT
if(ProjectItemTypeEnum.INPUT.getValue().equals(header.getType())){
if(originalData.containsKey(key)){
if(StringUtils.isNotBlank(originalData.get(key).toString())){
userAnswer.add((String) originalData.get(key));
}else{
userAnswer.add(StrConstant.EPMETY_STR);
if (ProjectItemTypeEnum.INPUT.getValue().equals(header.getType())) {
if (originalData.containsKey(key)) {
if (StringUtils.isNotBlank(originalData.get(key).toString())) {
mapUnit.put(header.getFormItemId(),(String) originalData.get(key));
} else {
mapUnit.put(header.getFormItemId(),StrConstant.EPMETY_STR);
}
}else{
log.warn("没有当前的key:,可能用户没填写吧"+key);
userAnswer.add(StrConstant.HYPHEN);
} else {
log.warn("没有当前的key:,可能用户没填写吧" + key);
mapUnit.put(header.getFormItemId(),StrConstant.HYPHEN);
}
}
//省市联动: PROVINCE_CITY
if(ProjectItemTypeEnum.PROVINCE_CITY.getValue().equals(header.getType())){
if(originalData.containsKey(key)){
List<String> provinceCityList= (List<String>) originalData.get(key);
if(!CollectionUtils.isEmpty(provinceCityList)){
userAnswer.add(StringUtils.join(provinceCityList,StrConstant.HYPHEN));
}else{
userAnswer.add(StrConstant.EPMETY_STR);
if (ProjectItemTypeEnum.PROVINCE_CITY.getValue().equals(header.getType())) {
if (originalData.containsKey(key)) {
List<String> provinceCityList = (List<String>) originalData.get(key);
if (!CollectionUtils.isEmpty(provinceCityList)) {
mapUnit.put(header.getFormItemId(),StringUtils.join(provinceCityList, StrConstant.HYPHEN));
} else {
mapUnit.put(header.getFormItemId(),StrConstant.EPMETY_STR);
}
}else{
log.warn("没有当前的key:,可能用户没填写吧"+key);
userAnswer.add(StrConstant.HYPHEN);
} else {
log.warn("没有当前的key:,可能用户没填写吧" + key);
mapUnit.put(header.getFormItemId(),StrConstant.HYPHEN);
}
}
//地理位置:INPUT_MAP
if(ProjectItemTypeEnum.INPUT_MAP.getValue().equals(header.getType())){
if(originalData.containsKey(key)){
List<String> inputMap= (List<String>) originalData.get(key);
log.info("地理位置:"+JSON.toJSONString(inputMap,true));
if (ProjectItemTypeEnum.INPUT_MAP.getValue().equals(header.getType())) {
if (originalData.containsKey(key)) {
List<String> inputMap = (List<String>) originalData.get(key);
log.info("地理位置:" + JSON.toJSONString(inputMap, true));
if (!CollectionUtils.isEmpty(inputMap) && inputMap.size() == 3) {
userAnswer.add(inputMap.get(2));
}else{
userAnswer.add(StrConstant.EPMETY_STR);
mapUnit.put(header.getFormItemId(),inputMap.get(2));
} else {
mapUnit.put(header.getFormItemId(),StrConstant.EPMETY_STR);
}
}else{
log.warn("没有当前的key:,可能用户没填写吧"+key);
userAnswer.add(StrConstant.HYPHEN);
} else {
log.warn("没有当前的key:,可能用户没填写吧" + key);
mapUnit.put(header.getFormItemId(),StrConstant.HYPHEN);
}
}
}
dataList.add(userAnswer);
}//end
dataMap.add(mapUnit);
}
resultDTO.setTableHeaderList(tableHeaderList);
resultDTO.setDataList(dataList);
resultDTO.setDataMap(dataMap);
return resultDTO;
}
/**
* 有新的问卷显示小红点
*
* @param tokenDto
* @Param tokenDto
* @Return {@link RedPointResultDTO}
* @Author zhaoqifeng
* @Date 2021/9/23 10:05
*/
@Override
public RedPointResultDTO redPoint(TokenDto tokenDto) {
RedPointResultDTO result = new RedPointResultDTO();
List<String> orgList = govOrgService.getStaffOrgList(tokenDto.getUserId());
List<PrPublishRangeDTO> list = prPublishRangeService.getListByOrg(orgList);
if (CollectionUtils.isEmpty(list)) {
result.setRedPoint(NumConstant.ZERO_STR);
return result;
}
PrVistRecordDTO visitRecord = prVistRecordService.getNewestRecord(tokenDto.getUserId());
if (null == visitRecord) {
result.setRedPoint(NumConstant.ONE_STR);
return result;
}
if (list.get(0).getCreatedTime().compareTo(visitRecord.getCreatedTime()) > 0) {
result.setRedPoint(NumConstant.ONE_STR);
} else {
result.setRedPoint(NumConstant.ZERO_STR);
}
return result;
}
@Override
public PrUserProjectEntity getProjectEntityBykey(String key) {
LambdaQueryWrapper<PrUserProjectEntity> query = new LambdaQueryWrapper<>();
query.eq(PrUserProjectEntity::getKey, key);
return baseDao.selectOne(query);
}
}

22
epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/epmettduck/impl/PrVistRecordServiceImpl.java

@ -17,6 +17,7 @@
package com.epmet.dataaggre.service.epmettduck.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.epmet.commons.dynamic.datasource.annotation.DataSource;
@ -30,6 +31,7 @@ import com.epmet.dataaggre.dto.epmettduck.PrVistRecordDTO;
import com.epmet.dataaggre.entity.epmettduck.PrVistRecordEntity;
import com.epmet.dataaggre.service.epmettduck.PrVistRecordService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -101,4 +103,24 @@ public class PrVistRecordServiceImpl extends BaseServiceImpl<PrVistRecordDao, Pr
baseDao.deleteBatchIds(Arrays.asList(ids));
}
/**
* @param staffId
* @Description 获取最新访问记录
* @Param staffId
* @Return {@link PrVistRecordDTO}
* @Author zhaoqifeng
* @Date 2021/9/23 14:16
*/
@Override
public PrVistRecordDTO getNewestRecord(String staffId) {
LambdaQueryWrapper<PrVistRecordEntity> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(PrVistRecordEntity::getUserId, staffId);
wrapper.orderByDesc(PrVistRecordEntity::getCreatedTime);
List<PrVistRecordEntity> list = baseDao.selectList(wrapper);
if (CollectionUtils.isEmpty(list)) {
return null;
}
return ConvertUtils.sourceToTarget(list, PrVistRecordDTO.class).get(0);
}
}

1
epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/epmetuser/impl/EpmetUserServiceImpl.java

@ -600,6 +600,7 @@ public class EpmetUserServiceImpl implements EpmetUserService {
}
result.setAgencyId(agencyDTO.getId());
result.setAgencyName(agencyDTO.getOrganizationName());
result.setAgencyPIds(agencyDTO.getPids());
StaffOrgRelationResultDTO fromOrgTypeDto = govOrgService.getStaffFromOrgType(staffId);
String fromOrgType = OrgTypeEnum.AGENCY.getCode();
if (fromOrgTypeDto != null){

9
epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/govorg/GovOrgService.java

@ -145,4 +145,13 @@ public interface GovOrgService {
* @Date 2021/9/17 14:03
*/
List<OrgTreeResultDTO> getAgencyTree(TokenDto tokenDto, SubOrgFormDTO formDTO);
/**
* @Description 工作人员所在的组织部门网格
* @Param staffId
* @Return {@link List< String>}
* @Author zhaoqifeng
* @Date 2021/9/23 10:14
*/
List<String> getStaffOrgList(String staffId);
}

18
epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/govorg/impl/GovOrgServiceImpl.java

@ -509,13 +509,27 @@ public class GovOrgServiceImpl implements GovOrgService {
*/
@Override
public List<OrgTreeResultDTO> getAgencyTree(TokenDto tokenDto, SubOrgFormDTO formDTO) {
CustomerStaffInfoCacheResult staffInfo = CustomerStaffRedis.getStaffInfo(tokenDto.getCustomerId(), tokenDto.getUserId());
List<OrgTreeResultDTO> list = new ArrayList<>();
if ("resi".equals(formDTO.getClient())) {
list.add(customerAgencyDao.getResiOrgTree(formDTO.getAgencyId()));
list.add(customerAgencyDao.getResiOrgTree(staffInfo.getAgencyId()));
return list;
}
list.add(customerAgencyDao.getOrgTree(formDTO.getAgencyId()));
list.add(customerAgencyDao.getOrgTree(staffInfo.getAgencyId()));
return list;
}
/**
* @param staffId
* @Description 工作人员所在的组织部门网格
* @Param staffId
* @Return {@link List< String>}
* @Author zhaoqifeng
* @Date 2021/9/23 10:14
*/
@Override
public List<String> getStaffOrgList(String staffId) {
return customerAgencyDao.getOrgList(staffId);
}
}

193
epmet-module/data-aggregator/data-aggregator-server/src/main/java/com/epmet/dataaggre/service/impl/QuestionnaireServiceImpl.java

@ -0,0 +1,193 @@
package com.epmet.dataaggre.service.impl;
import com.epmet.commons.tools.constant.AppClientConstant;
import com.epmet.commons.tools.constant.ServiceConstant;
import com.epmet.commons.tools.dto.form.IdAndNameDTO;
import com.epmet.commons.tools.dto.result.CustomerStaffInfoCacheResult;
import com.epmet.commons.tools.exception.EpmetErrorCode;
import com.epmet.commons.tools.exception.RenException;
import com.epmet.commons.tools.feign.ResultDataResolver;
import com.epmet.commons.tools.redis.RedisKeys;
import com.epmet.commons.tools.redis.RedisUtils;
import com.epmet.commons.tools.redis.common.CustomerStaffRedis;
import com.epmet.commons.tools.utils.Result;
import com.epmet.dataaggre.dto.epmettduck.result.PermissionValidateResultDTO;
import com.epmet.dataaggre.entity.epmettduck.PrPublishRangeEntity;
import com.epmet.dataaggre.entity.epmettduck.PrUserProjectEntity;
import com.epmet.dataaggre.service.QuestionnaireService;
import com.epmet.dataaggre.service.epmettduck.PrPublishRangeService;
import com.epmet.dataaggre.service.epmettduck.PrUserProjectService;
import com.epmet.dto.CustomerGridDTO;
import com.epmet.dto.form.CustomerGridFormDTO;
import com.epmet.feign.GovOrgOpenFeignClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@Service
@Slf4j
public class QuestionnaireServiceImpl implements QuestionnaireService, ResultDataResolver {
/** 调查问卷有效期 15min */
public static final long QUESTIONNAIRE_EXPIRE_SECONDS = 15 * 60;
@Autowired
private PrUserProjectService prUserProjectService;
@Autowired
private PrPublishRangeService prPublishRangeService;
@Autowired
private GovOrgOpenFeignClient govOrgOpenFeignClient;
@Autowired
private RedisUtils redisUtils;
@Autowired
private CustomerStaffRedis customerStaffRedis;
/**
* @description 居民端调查问卷权限校验
*
* @param projectKey
* @param userId
* @param gridId
* @return
* @author wxz
* @date 2021.09.23 17:45:25
*/
public PermissionValidateResultDTO resiPermissionValidate(String projectKey, String userId, String gridId) {
PrUserProjectEntity project = prUserProjectService.getProjectEntityBykey(projectKey);
if (project == null || !AppClientConstant.APP_RESI.equals(project.getClient())) {
// 工作端只能看到发布到居民端的
log.warn("【调查问卷】居民端无法查看发布到工作端的调查问卷,staffId:{}, projectKey:{}", userId, projectKey);
return generateValidateResult(userId, projectKey, false);
}
CustomerGridFormDTO form = new CustomerGridFormDTO();
form.setGridId(gridId);
Result<CustomerGridDTO> gridInfoResult = govOrgOpenFeignClient.getGridBaseInfoByGridId(form);
CustomerGridDTO gridInfo = getResultDataOrThrowsException(gridInfoResult, ServiceConstant.GOV_ORG_SERVER, EpmetErrorCode.SERVER_ERROR.getCode(), "【调查问卷】校验访问权限,查询网格信息失败");
// 网格父级ID列表:网格ID(拼接起来,冒号分割)
String gridIdPath = gridInfo.getPids().concat(":").concat(gridInfo.getId());
List<PrPublishRangeEntity> publishRangeEntity = prPublishRangeService.getPublishRangeEntity(projectKey);
PermissionValidateResultDTO r = new PermissionValidateResultDTO();
for (PrPublishRangeEntity rangeEntity : publishRangeEntity) {
if (gridIdPath.contains(rangeEntity.getOrgIds())) {
return generateValidateResult(userId, projectKey, true);
}
}
r.setPermitted(false);
return r;
}
@Override
public PermissionValidateResultDTO govPermissionValidate(String projectKey, String staffId, String customerId) {
PrUserProjectEntity project = prUserProjectService.getProjectEntityBykey(projectKey);
if (project == null || !"gov".equals(project.getClient())) {
// 工作端只能看到发布到工作端的
log.warn("【调查问卷】工作端无法查看发布到居民端的调查问卷,staffId:{}, projectKey:{}", staffId, projectKey);
return generateValidateResult(staffId, projectKey, false);
}
List<String> gridRangeOrgIds = new ArrayList<>();
List<String> agencyRangeOrgIds = new ArrayList<>();
List<String> deptRangeOrgIds = new ArrayList<>();
// 将发布范围分别放到3个不同的列表中
List<PrPublishRangeEntity> publishRangeEntitys = prPublishRangeService.getPublishRangeEntity(projectKey);
publishRangeEntitys.forEach(rangeEntity -> {
if ("grid".equals(rangeEntity.getOrgType())) {
gridRangeOrgIds.add(rangeEntity.getOrgIds());
} else if ("agency".equals(rangeEntity.getOrgType())) {
agencyRangeOrgIds.add(rangeEntity.getOrgIds());
} else if ("dept".equals(rangeEntity.getOrgType())) {
deptRangeOrgIds.add(rangeEntity.getOrgIds());
} else {
throw new RenException(EpmetErrorCode.SERVER_ERROR.getCode(), String.format("【调查问卷】未知的发布范围类型:%s", rangeEntity.getOrgType()));
}
});
CustomerStaffInfoCacheResult staffInfo = customerStaffRedis.getStaffInfo(customerId, staffId);
PermissionValidateResultDTO r = null;
//if ("agency".equals(staffInfo.getFromOrgType())) {
// // 来自agency
//
//} else if ("grid".equals(staffInfo.getFromOrgType())) {
// List<IdAndNameDTO> belongGridList = staffInfo.getGridList();
//
//} else if ("dept".equals(staffInfo.getFromOrgType())) {
//
//}
String agencyId = staffInfo.getAgencyId();
String agencyPIds = staffInfo.getAgencyPIds();
// 网格范围内的权限判断
List<IdAndNameDTO> staffGridList = staffInfo.getGridList();
for (IdAndNameDTO gridIdAndName : staffGridList) {
// 工作人员所属的 父orgId路径:网格id
String staffGridIdPath = (StringUtils.isEmpty(agencyPIds) ? "" : agencyPIds.concat(":")).concat(agencyId).concat(":").concat(gridIdAndName.getId());
for (String gridRangeOrgId : gridRangeOrgIds) {
if (staffGridIdPath.contains(gridRangeOrgId)) {
r = generateValidateResult(staffId, projectKey, true);
return r;
}
}
}
// dept范围内的权限判断
List<IdAndNameDTO> staffDeptList = staffInfo.getDeptList();
for (IdAndNameDTO deptIdAndName : staffDeptList) {
// 工作人员所属的 父orgId路径:网格id
String staffDeptIdPath = (StringUtils.isEmpty(agencyPIds) ? "" : agencyPIds.concat(":")).concat(agencyId).concat(":").concat(deptIdAndName.getId());
for (String deptRangeOrgIdPath : deptRangeOrgIds) {
if (staffDeptIdPath.contains(deptRangeOrgIdPath)) {
r = generateValidateResult(staffId, projectKey, true);
return r;
}
}
}
// agency范围内的权限判断
String staffAgencyIdPath = (StringUtils.isEmpty(agencyPIds) ? "" : agencyPIds.concat(":")).concat(agencyId);
for (String agencyRangeOrgId : agencyRangeOrgIds) {
if (staffAgencyIdPath.contains(agencyRangeOrgId)) {
r = generateValidateResult(staffId, projectKey, true);
return r;
}
}
// 如果上述范围中都不能判断通过,那么返回一个不通过的结果给到前端
r = generateValidateResult(staffId, projectKey, false);
return r;
}
/**
* @description 生成权限允许的返回结果
*
* @param userId
* @param projectKey
* @param permitted 是否允许访问
* @return
* @author wxz
* @date 2021.09.23 23:19:17
*/
private PermissionValidateResultDTO generateValidateResult(String userId, String projectKey, Boolean permitted) {
PermissionValidateResultDTO d = new PermissionValidateResultDTO();
d.setPermitted(permitted);
if (permitted) {
String accessKey = UUID.randomUUID().toString().replace("-", "");
redisUtils.set(RedisKeys.getQuestionnaireAccessKey(userId, projectKey), accessKey, QUESTIONNAIRE_EXPIRE_SECONDS);
d.setAccessKey(accessKey);
}
return d;
}
}

2
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@

23
epmet-module/data-aggregator/data-aggregator-server/src/main/resources/mapper/epmettduck/PrUserProjectDao.xml

@ -73,25 +73,26 @@
DISTINCT project_key
FROM pr_publish_range
WHERE del_flag = 0
AND #{orgIds} LIKE CONCAT(org_ids,'%')
AND (
<foreach collection="orgIds" item="orgId" separator=" OR ">
#{orgId} LIKE CONCAT(org_ids,'%')
</foreach>
)
</select>
<!-- 根据keys查询project -->
<select id="queryProjectList" resultType="com.epmet.dataaggre.dto.epmettduck.result.TDuckListResultDTO">
select * from pr_user_project
where del_flag = 0
AND status = #{status}
AND client = #{client}
AND `key` in (
select up.*,ps.is_everyone_write_once_uid from pr_user_project up
LEFT JOIN pr_user_project_setting ps ON (ps.project_key = up.`key` AND ps.del_flag = 0)
where up.del_flag = 0
AND up.status = #{status}
AND up.client = #{client}
AND up.`key` in (
<foreach collection="keys" item="key" separator=",">
#{key}
</foreach>
)
ORDER BY created_time DESC
ORDER BY up.created_time DESC
</select>
<!-- 查询头部信息【问卷调查的名字和描述】 -->
<select id="selectHeaderInfoByKey" resultType="com.epmet.dataaggre.entity.epmettduck.PrUserProjectEntity">
select * from pr_user_project where del_flag = 0 and `key` = #{key}
</select>
</mapper>

5
epmet-module/data-aggregator/data-aggregator-server/src/main/resources/mapper/epmettduck/PrUserProjectResultDao.xml

@ -3,4 +3,9 @@
<mapper namespace="com.epmet.dataaggre.dao.epmettduck.PrUserProjectResultDao">
<select id="selectFillRecordByUserId" resultType="java.lang.String">
SELECT DISTINCT project_key FROM pr_user_project_result
WHERE del_flag = 0
AND user_id = #{userId}
</select>
</mapper>

6
epmet-module/data-aggregator/data-aggregator-server/src/main/resources/mapper/epmettduck/PrVistRecordDao.xml

@ -3,10 +3,4 @@
<mapper namespace="com.epmet.dataaggre.dao.epmettduck.PrVistRecordDao">
<!-- 根据userId查询是否已填 -->
<select id="selectVisitRecordByUserId" resultType="java.lang.String">
SELECT project_key FROM pr_vist_record
WHERE del_flag = 0
AND user_id = #{userId}
</select>
</mapper>

27
epmet-module/data-aggregator/data-aggregator-server/src/main/resources/mapper/govorg/CustomerAgencyDao.xml

@ -201,7 +201,7 @@
select
ID AS orgId,
ORGANIZATION_NAME AS orgName,
'agency' AS orgName,
'agency' AS orgType,
CONCAT(PIDS,ID) AS orgPids
from
@ -253,7 +253,7 @@
select
ID AS orgId,
ORGANIZATION_NAME AS orgName,
'agency' AS orgName,
'agency' AS orgType,
CONCAT(PIDS,ID) AS orgPids
from
@ -262,5 +262,28 @@
DEL_FLAG = 0
AND ID = #{agencyId}
</select>
<select id="getOrgList" resultType="java.lang.String">
SELECT
AGENCY_ID AS orgId
FROM
customer_staff_agency
WHERE
DEL_FLAG = '0'
AND USER_ID = #{staffId} UNION
SELECT
GRID_ID AS orgId
FROM
customer_staff_grid
WHERE
DEL_FLAG = '0'
AND USER_ID = #{staffId} UNION
SELECT
DEPARTMENT_ID AS orgId
FROM
customer_staff_department
WHERE
DEL_FLAG = '0'
AND USER_ID = #{staffId}
</select>
</mapper>

6
epmet-module/data-report/data-report-server/pom.xml

@ -167,6 +167,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<!--flyway migration 数据库迁移工具-->
<spring.flyway.enabled>false</spring.flyway.enabled>
@ -219,6 +221,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>false</nacos.service-list-changed-listening.enable>
<!--flyway migration 数据库迁移工具-->
<spring.flyway.enabled>false</spring.flyway.enabled>
@ -271,6 +275,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<!--flyway migration 数据库迁移工具-->
<spring.flyway.enabled>true</spring.flyway.enabled>

161
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<String> observingServers = new ArrayList<>(33);
@PostConstruct
public void init() {
namingService = discoveryProperties.namingServiceInstance();
// 启动监听
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("NacosServiceListWatchingRegisterer");
return thread;
}
});
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS);
}
public class EpmetNacosServiceListListener implements Runnable {
@Override
public void run() {
doRefreshServerList();
}
/**
* @param
* @return
* @description 执行刷新
* @author wxz
* @date 2021.09.22 16:04:49
*/
private synchronized void doRefreshServerList() {
ListView<String> serviceListView = null;
try {
serviceListView = namingService.getServicesOfServer(1, 100);
//启动监听
if (serviceListView == null || serviceListView.getCount() == 0) {
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
return;
}
List<String> serviceList = serviceListView.getData();
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList);
for (String service : serviceList) {
try {
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
if (observingServers.contains(service)) {
continue;
}
namingService.subscribe(service, new EventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
NamingEvent namingEvent = (NamingEvent) event;
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances());
doRefreshServerList(service);
}
}
});
// 将该服务加入到监听列表中
observingServers.add(service);
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace);
}
}
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace);
}
}
/**
* @param serviceName
* @return
* @description 刷新ServerList
* @author wxz
* @date 2021.09.22 09:29:16
*/
private void doRefreshServerList(String serviceName) {
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
// try {
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
// restOfInitMethod.setAccessible(true);
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
// }
//}
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
// 暂且 1 try
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
if (loadBalancer instanceof DynamicServerListLoadBalancer) {
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer;
dslb.updateListOfServers();
}
}
}
}

2
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@

6
epmet-module/data-statistical/data-statistical-server/pom.xml

@ -241,6 +241,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<!--flyway migration 数据库迁移工具-->
<spring.flyway.enabled>false</spring.flyway.enabled>
@ -361,6 +363,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>false</nacos.service-list-changed-listening.enable>
<!--flyway migration 数据库迁移工具-->
<spring.flyway.enabled>false</spring.flyway.enabled>
@ -481,6 +485,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<!--flyway migration 数据库迁移工具-->
<spring.flyway.enabled>false</spring.flyway.enabled>

161
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<String> observingServers = new ArrayList<>(33);
@PostConstruct
public void init() {
namingService = discoveryProperties.namingServiceInstance();
// 启动监听
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("NacosServiceListWatchingRegisterer");
return thread;
}
});
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS);
}
public class EpmetNacosServiceListListener implements Runnable {
@Override
public void run() {
doRefreshServerList();
}
/**
* @param
* @return
* @description 执行刷新
* @author wxz
* @date 2021.09.22 16:04:49
*/
private synchronized void doRefreshServerList() {
ListView<String> serviceListView = null;
try {
serviceListView = namingService.getServicesOfServer(1, 100);
//启动监听
if (serviceListView == null || serviceListView.getCount() == 0) {
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
return;
}
List<String> serviceList = serviceListView.getData();
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList);
for (String service : serviceList) {
try {
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
if (observingServers.contains(service)) {
continue;
}
namingService.subscribe(service, new EventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
NamingEvent namingEvent = (NamingEvent) event;
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances());
doRefreshServerList(service);
}
}
});
// 将该服务加入到监听列表中
observingServers.add(service);
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace);
}
}
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace);
}
}
/**
* @param serviceName
* @return
* @description 刷新ServerList
* @author wxz
* @date 2021.09.22 09:29:16
*/
private void doRefreshServerList(String serviceName) {
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
// try {
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
// restOfInitMethod.setAccessible(true);
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
// }
//}
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
// 暂且 1 try
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
if (loadBalancer instanceof DynamicServerListLoadBalancer) {
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer;
dslb.updateListOfServers();
}
}
}
}

7
epmet-module/data-statistical/data-statistical-server/src/main/java/com/epmet/dao/stats/FactPartyMemberVanguardAgencyDailyDao.java

@ -37,8 +37,9 @@ public interface FactPartyMemberVanguardAgencyDailyDao extends BaseDao<FactParty
* @date 2021/5/17 17:19
* @param customerId
* @param dateId
* @param limit
* @return int
*/
int deleteDailyData(@Param("customerId") String customerId, @Param("dateId") String dateId);
}
int deleteDailyData(@Param("customerId") String customerId, @Param("dateId") String dateId, Integer limit);
}

5
epmet-module/data-statistical/data-statistical-server/src/main/java/com/epmet/dao/stats/FactPartyMemberVanguardGridDailyDao.java

@ -36,7 +36,8 @@ public interface FactPartyMemberVanguardGridDailyDao extends BaseDao<FactPartyMe
* @date 2021/5/17 17:19
* @param customerId
* @param dateId
* @param limit
* @return int
*/
int deleteDailyData(@Param("customerId") String customerId, @Param("dateId") String dateId);
}
int deleteDailyData(@Param("customerId") String customerId, @Param("dateId") String dateId, Integer limit);
}

37
epmet-module/data-statistical/data-statistical-server/src/main/java/com/epmet/service/impl/StatsPartyMemberVanguardServiceImpl.java

@ -6,7 +6,6 @@ import com.epmet.constant.OrgTypeConstant;
import com.epmet.dto.StatsFormDTO;
import com.epmet.dto.extract.result.OrgStatisticsResultDTO;
import com.epmet.dto.stats.DimAgencyDTO;
import com.epmet.dto.stats.DimGridDTO;
import com.epmet.entity.stats.DimGridEntity;
import com.epmet.entity.stats.FactPartyMemberVanguardAgencyDailyEntity;
import com.epmet.entity.stats.FactPartyMemberVanguardGridDailyEntity;
@ -16,6 +15,7 @@ import com.epmet.service.stats.*;
import com.epmet.util.DimIdGenerator;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
@ -191,10 +191,20 @@ public class StatsPartyMemberVanguardServiceImpl implements StatsPartyMemberVang
}
});
}
//删除旧数据
factPartyMemberVanguardAgencyDailyService.deleteDailyData(customerId, dimId.getDateId());
//批量插入
factPartyMemberVanguardAgencyDailyService.insertBatch(vanguardList);
//删除旧数据 每次删除1000
Integer effectRow;
do {
effectRow = factPartyMemberVanguardAgencyDailyService.deleteDailyData(customerId, dimId.getDateId(), NumConstant.ONE_THOUSAND);
} while (effectRow != null && effectRow > NumConstant.ZERO);
//批量插入 每次100
if (CollectionUtils.isEmpty(vanguardList)) {
log.warn("customerAgencyStats insert list is empty,customerId:{},dateId:{}", customerId, dimId.getDateId());
}
ListUtils.partition(vanguardList, NumConstant.ONE_HUNDRED)
.forEach(part -> factPartyMemberVanguardAgencyDailyService.insertBatch(part));
}
}
/**
@ -327,10 +337,19 @@ public class StatsPartyMemberVanguardServiceImpl implements StatsPartyMemberVang
}
});
}
//删除旧数据
factPartyMemberVanguardGridDailyService.deleteDailyData(customerId, dimId.getDateId());
//批量插入
factPartyMemberVanguardGridDailyService.insertBatch(vanguardList);
//删除旧数据 每次删除1000
Integer effectRow;
do {
effectRow = factPartyMemberVanguardGridDailyService.deleteDailyData(customerId, dimId.getDateId(), NumConstant.ONE_THOUSAND);
} while (effectRow != null && effectRow > NumConstant.ZERO);
//批量插入 每次100
if (CollectionUtils.isEmpty(vanguardList)){
log.warn("customerGridStats insert list is empty,customerId:{},dateId:{}", customerId, dimId.getDateId());
}
ListUtils.partition(vanguardList, NumConstant.ONE_HUNDRED)
.forEach(part -> factPartyMemberVanguardGridDailyService.insertBatch(part));
}
}

5
epmet-module/data-statistical/data-statistical-server/src/main/java/com/epmet/service/stats/FactPartyMemberVanguardAgencyDailyService.java

@ -99,7 +99,8 @@ public interface FactPartyMemberVanguardAgencyDailyService extends BaseService<F
* @date 2021/5/17 15:55
* @param customerId
* @param dateId
* @param limit
* @return void
*/
void deleteDailyData(String customerId, String dateId);
}
Integer deleteDailyData(String customerId, String dateId, Integer limit);
}

5
epmet-module/data-statistical/data-statistical-server/src/main/java/com/epmet/service/stats/FactPartyMemberVanguardGridDailyService.java

@ -99,7 +99,8 @@ public interface FactPartyMemberVanguardGridDailyService extends BaseService<Fac
* @date 2021/5/17 15:55
* @param customerId
* @param dateId
* @param limit
* @return void
*/
void deleteDailyData(String customerId, String dateId);
}
Integer deleteDailyData(String customerId, String dateId, Integer limit);
}

7
epmet-module/data-statistical/data-statistical-server/src/main/java/com/epmet/service/stats/impl/FactPartyMemberVanguardAgencyDailyServiceImpl.java

@ -105,14 +105,15 @@ public class FactPartyMemberVanguardAgencyDailyServiceImpl extends BaseServiceIm
*
* @param customerId
* @param dateId
* @param limit
* @return void
* @author zhaoqifeng
* @date 2021/5/17 15:55
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteDailyData(String customerId, String dateId) {
baseDao.deleteDailyData(customerId, dateId);
public Integer deleteDailyData(String customerId, String dateId, Integer limit) {
return baseDao.deleteDailyData(customerId, dateId, limit);
}
}
}

7
epmet-module/data-statistical/data-statistical-server/src/main/java/com/epmet/service/stats/impl/FactPartyMemberVanguardGridDailyServiceImpl.java

@ -105,14 +105,15 @@ public class FactPartyMemberVanguardGridDailyServiceImpl extends BaseServiceImpl
*
* @param customerId
* @param dateId
* @param limit
* @return void
* @author zhaoqifeng
* @date 2021/5/17 15:55
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteDailyData(String customerId, String dateId) {
baseDao.deleteDailyData(customerId, dateId);
public Integer deleteDailyData(String customerId, String dateId, Integer limit) {
return baseDao.deleteDailyData(customerId, dateId, limit);
}
}
}

2
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@

3
epmet-module/data-statistical/data-statistical-server/src/main/resources/mapper/stats/FactPartyMemberVanguardAgencyDailyDao.xml

@ -34,7 +34,8 @@
</resultMap>
<delete id="deleteDailyData">
delete from fact_party_member_vanguard_agency_daily where customer_id = #{customerId} and DATE_ID = #{dateId}
limit #{limit}
</delete>
</mapper>
</mapper>

3
epmet-module/data-statistical/data-statistical-server/src/main/resources/mapper/stats/FactPartyMemberVanguardGridDailyDao.xml

@ -34,7 +34,8 @@
</resultMap>
<delete id="deleteDailyData">
delete from fact_party_member_vanguard_grid_daily where customer_id = #{customerId} and DATE_ID = #{dateId}
limit #{limit}
</delete>
</mapper>
</mapper>

6
epmet-module/epmet-activiti/epmet-activiti-server/pom.xml

@ -181,6 +181,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
</properties>
@ -213,6 +215,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>false</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
</properties>
@ -242,6 +246,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>true</spring.flyway.enabled>
</properties>

2
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@

6
epmet-module/epmet-common-service/common-service-server/pom.xml

@ -123,6 +123,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
<!--亿联云消息网关配置-->
@ -169,6 +171,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>false</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
<!--亿联云消息网关配置-->
@ -213,6 +217,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>true</spring.flyway.enabled>
<!--亿联云消息网关配置-->

161
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<String> observingServers = new ArrayList<>(33);
@PostConstruct
public void init() {
namingService = discoveryProperties.namingServiceInstance();
// 启动监听
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("NacosServiceListWatchingRegisterer");
return thread;
}
});
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS);
}
public class EpmetNacosServiceListListener implements Runnable {
@Override
public void run() {
doRefreshServerList();
}
/**
* @param
* @return
* @description 执行刷新
* @author wxz
* @date 2021.09.22 16:04:49
*/
private synchronized void doRefreshServerList() {
ListView<String> serviceListView = null;
try {
serviceListView = namingService.getServicesOfServer(1, 100);
//启动监听
if (serviceListView == null || serviceListView.getCount() == 0) {
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
return;
}
List<String> serviceList = serviceListView.getData();
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList);
for (String service : serviceList) {
try {
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
if (observingServers.contains(service)) {
continue;
}
namingService.subscribe(service, new EventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
NamingEvent namingEvent = (NamingEvent) event;
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances());
doRefreshServerList(service);
}
}
});
// 将该服务加入到监听列表中
observingServers.add(service);
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace);
}
}
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace);
}
}
/**
* @param serviceName
* @return
* @description 刷新ServerList
* @author wxz
* @date 2021.09.22 09:29:16
*/
private void doRefreshServerList(String serviceName) {
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
// try {
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
// restOfInitMethod.setAccessible(true);
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
// }
//}
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
// 暂且 1 try
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
if (loadBalancer instanceof DynamicServerListLoadBalancer) {
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer;
dslb.updateListOfServers();
}
}
}
}

2
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@

7
epmet-module/epmet-demo/epmet-demo-server/pom.xml

@ -127,6 +127,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
</properties>
</profile>
<profile>
@ -136,7 +138,7 @@
</activation>-->
<properties>
<server.port>8088</server.port>
<spring.profiles.active>dev</spring.profiles.active>
<spring.profiles.active>test</spring.profiles.active>
<!-- 数据库配置-->
<spring.datasource.druid.url>
@ -157,6 +159,9 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
</properties>
</profile>
</profiles>

161
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<String> observingServers = new ArrayList<>(33);
@PostConstruct
public void init() {
namingService = discoveryProperties.namingServiceInstance();
// 启动监听
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("NacosServiceListWatchingRegisterer");
return thread;
}
});
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS);
}
public class EpmetNacosServiceListListener implements Runnable {
@Override
public void run() {
doRefreshServerList();
}
/**
* @param
* @return
* @description 执行刷新
* @author wxz
* @date 2021.09.22 16:04:49
*/
private synchronized void doRefreshServerList() {
ListView<String> serviceListView = null;
try {
serviceListView = namingService.getServicesOfServer(1, 100);
//启动监听
if (serviceListView == null || serviceListView.getCount() == 0) {
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
return;
}
List<String> serviceList = serviceListView.getData();
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList);
for (String service : serviceList) {
try {
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
if (observingServers.contains(service)) {
continue;
}
namingService.subscribe(service, new EventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
NamingEvent namingEvent = (NamingEvent) event;
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances());
doRefreshServerList(service);
}
}
});
// 将该服务加入到监听列表中
observingServers.add(service);
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace);
}
}
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace);
}
}
/**
* @param serviceName
* @return
* @description 刷新ServerList
* @author wxz
* @date 2021.09.22 09:29:16
*/
private void doRefreshServerList(String serviceName) {
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
// try {
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
// restOfInitMethod.setAccessible(true);
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
// }
//}
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
// 暂且 1 try
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
if (loadBalancer instanceof DynamicServerListLoadBalancer) {
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer;
dslb.updateListOfServers();
}
}
}
}

2
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@

6
epmet-module/epmet-ext/epmet-ext-server/pom.xml

@ -215,6 +215,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
@ -254,6 +256,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>false</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
@ -293,6 +297,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>true</spring.flyway.enabled>

161
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<String> observingServers = new ArrayList<>(33);
@PostConstruct
public void init() {
namingService = discoveryProperties.namingServiceInstance();
// 启动监听
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("NacosServiceListWatchingRegisterer");
return thread;
}
});
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS);
}
public class EpmetNacosServiceListListener implements Runnable {
@Override
public void run() {
doRefreshServerList();
}
/**
* @param
* @return
* @description 执行刷新
* @author wxz
* @date 2021.09.22 16:04:49
*/
private synchronized void doRefreshServerList() {
ListView<String> serviceListView = null;
try {
serviceListView = namingService.getServicesOfServer(1, 100);
//启动监听
if (serviceListView == null || serviceListView.getCount() == 0) {
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
return;
}
List<String> serviceList = serviceListView.getData();
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList);
for (String service : serviceList) {
try {
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
if (observingServers.contains(service)) {
continue;
}
namingService.subscribe(service, new EventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
NamingEvent namingEvent = (NamingEvent) event;
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances());
doRefreshServerList(service);
}
}
});
// 将该服务加入到监听列表中
observingServers.add(service);
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace);
}
}
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace);
}
}
/**
* @param serviceName
* @return
* @description 刷新ServerList
* @author wxz
* @date 2021.09.22 09:29:16
*/
private void doRefreshServerList(String serviceName) {
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
// try {
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
// restOfInitMethod.setAccessible(true);
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
// }
//}
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
// 暂且 1 try
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
if (loadBalancer instanceof DynamicServerListLoadBalancer) {
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer;
dslb.updateListOfServers();
}
}
}
}

2
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@

8
epmet-module/epmet-heart/epmet-heart-server/pom.xml

@ -133,6 +133,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
<openapi.scan.server.url>https://epmet-dev.elinkservice.cn/api/epmetscan/api</openapi.scan.server.url>
@ -174,6 +176,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>false</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
<openapi.scan.server.url>https://epmet-dev.elinkservice.cn/api/epmetscan/api</openapi.scan.server.url>
@ -215,6 +219,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>true</spring.flyway.enabled>
<openapi.scan.server.url>https://epmet-dev.elinkservice.cn/api/epmetscan/api</openapi.scan.server.url>
@ -256,6 +262,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>true</spring.flyway.enabled>
<openapi.scan.server.url>https://epmet-open.elinkservice.cn/api/epmetscan/api</openapi.scan.server.url>

161
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<String> observingServers = new ArrayList<>(33);
@PostConstruct
public void init() {
namingService = discoveryProperties.namingServiceInstance();
// 启动监听
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("NacosServiceListWatchingRegisterer");
return thread;
}
});
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS);
}
public class EpmetNacosServiceListListener implements Runnable {
@Override
public void run() {
doRefreshServerList();
}
/**
* @param
* @return
* @description 执行刷新
* @author wxz
* @date 2021.09.22 16:04:49
*/
private synchronized void doRefreshServerList() {
ListView<String> serviceListView = null;
try {
serviceListView = namingService.getServicesOfServer(1, 100);
//启动监听
if (serviceListView == null || serviceListView.getCount() == 0) {
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
return;
}
List<String> serviceList = serviceListView.getData();
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList);
for (String service : serviceList) {
try {
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
if (observingServers.contains(service)) {
continue;
}
namingService.subscribe(service, new EventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
NamingEvent namingEvent = (NamingEvent) event;
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances());
doRefreshServerList(service);
}
}
});
// 将该服务加入到监听列表中
observingServers.add(service);
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace);
}
}
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace);
}
}
/**
* @param serviceName
* @return
* @description 刷新ServerList
* @author wxz
* @date 2021.09.22 09:29:16
*/
private void doRefreshServerList(String serviceName) {
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
// try {
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
// restOfInitMethod.setAccessible(true);
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
// }
//}
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
// 暂且 1 try
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
if (loadBalancer instanceof DynamicServerListLoadBalancer) {
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer;
dslb.updateListOfServers();
}
}
}
}

2
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@

6
epmet-module/epmet-job/epmet-job-server/pom.xml

@ -136,6 +136,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
<!--钉钉 机器人地址-->
@ -171,6 +173,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>false</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
<!--钉钉 机器人地址-->
@ -206,6 +210,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>true</spring.flyway.enabled>
<!--测试钉钉 机器人地址-->

161
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<String> observingServers = new ArrayList<>(33);
@PostConstruct
public void init() {
namingService = discoveryProperties.namingServiceInstance();
// 启动监听
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("NacosServiceListWatchingRegisterer");
return thread;
}
});
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS);
}
public class EpmetNacosServiceListListener implements Runnable {
@Override
public void run() {
doRefreshServerList();
}
/**
* @param
* @return
* @description 执行刷新
* @author wxz
* @date 2021.09.22 16:04:49
*/
private synchronized void doRefreshServerList() {
ListView<String> serviceListView = null;
try {
serviceListView = namingService.getServicesOfServer(1, 100);
//启动监听
if (serviceListView == null || serviceListView.getCount() == 0) {
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
return;
}
List<String> serviceList = serviceListView.getData();
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList);
for (String service : serviceList) {
try {
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
if (observingServers.contains(service)) {
continue;
}
namingService.subscribe(service, new EventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
NamingEvent namingEvent = (NamingEvent) event;
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances());
doRefreshServerList(service);
}
}
});
// 将该服务加入到监听列表中
observingServers.add(service);
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace);
}
}
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace);
}
}
/**
* @param serviceName
* @return
* @description 刷新ServerList
* @author wxz
* @date 2021.09.22 09:29:16
*/
private void doRefreshServerList(String serviceName) {
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
// try {
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
// restOfInitMethod.setAccessible(true);
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
// }
//}
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
// 暂且 1 try
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
if (loadBalancer instanceof DynamicServerListLoadBalancer) {
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer;
dslb.updateListOfServers();
}
}
}
}

2
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@

6
epmet-module/epmet-message/epmet-message-server/pom.xml

@ -182,6 +182,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
@ -231,6 +233,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>false</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
@ -279,6 +283,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>true</spring.flyway.enabled>

161
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<String> observingServers = new ArrayList<>(33);
@PostConstruct
public void init() {
namingService = discoveryProperties.namingServiceInstance();
// 启动监听
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("NacosServiceListWatchingRegisterer");
return thread;
}
});
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS);
}
public class EpmetNacosServiceListListener implements Runnable {
@Override
public void run() {
doRefreshServerList();
}
/**
* @param
* @return
* @description 执行刷新
* @author wxz
* @date 2021.09.22 16:04:49
*/
private synchronized void doRefreshServerList() {
ListView<String> serviceListView = null;
try {
serviceListView = namingService.getServicesOfServer(1, 100);
//启动监听
if (serviceListView == null || serviceListView.getCount() == 0) {
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
return;
}
List<String> serviceList = serviceListView.getData();
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList);
for (String service : serviceList) {
try {
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
if (observingServers.contains(service)) {
continue;
}
namingService.subscribe(service, new EventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
NamingEvent namingEvent = (NamingEvent) event;
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances());
doRefreshServerList(service);
}
}
});
// 将该服务加入到监听列表中
observingServers.add(service);
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace);
}
}
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace);
}
}
/**
* @param serviceName
* @return
* @description 刷新ServerList
* @author wxz
* @date 2021.09.22 09:29:16
*/
private void doRefreshServerList(String serviceName) {
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
// try {
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
// restOfInitMethod.setAccessible(true);
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
// }
//}
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
// 暂且 1 try
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
if (loadBalancer instanceof DynamicServerListLoadBalancer) {
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer;
dslb.updateListOfServers();
}
}
}
}

2
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@

6
epmet-module/epmet-oss/epmet-oss-server/pom.xml

@ -141,6 +141,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
@ -180,6 +182,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>false</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
<!--钉钉 机器人地址-->
@ -218,6 +222,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>true</spring.flyway.enabled>
<!--测试钉钉 机器人地址-->

161
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<String> observingServers = new ArrayList<>(33);
@PostConstruct
public void init() {
namingService = discoveryProperties.namingServiceInstance();
// 启动监听
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("NacosServiceListWatchingRegisterer");
return thread;
}
});
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS);
}
public class EpmetNacosServiceListListener implements Runnable {
@Override
public void run() {
doRefreshServerList();
}
/**
* @param
* @return
* @description 执行刷新
* @author wxz
* @date 2021.09.22 16:04:49
*/
private synchronized void doRefreshServerList() {
ListView<String> serviceListView = null;
try {
serviceListView = namingService.getServicesOfServer(1, 100);
//启动监听
if (serviceListView == null || serviceListView.getCount() == 0) {
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
return;
}
List<String> serviceList = serviceListView.getData();
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList);
for (String service : serviceList) {
try {
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
if (observingServers.contains(service)) {
continue;
}
namingService.subscribe(service, new EventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
NamingEvent namingEvent = (NamingEvent) event;
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances());
doRefreshServerList(service);
}
}
});
// 将该服务加入到监听列表中
observingServers.add(service);
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace);
}
}
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace);
}
}
/**
* @param serviceName
* @return
* @description 刷新ServerList
* @author wxz
* @date 2021.09.22 09:29:16
*/
private void doRefreshServerList(String serviceName) {
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
// try {
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
// restOfInitMethod.setAccessible(true);
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
// }
//}
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
// 暂且 1 try
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
if (loadBalancer instanceof DynamicServerListLoadBalancer) {
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer;
dslb.updateListOfServers();
}
}
}
}

2
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@

6
epmet-module/epmet-point/epmet-point-server/pom.xml

@ -154,6 +154,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
@ -195,6 +197,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
@ -236,6 +240,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>true</spring.flyway.enabled>

161
epmet-module/epmet-point/epmet-point-server/src/main/java/com/epmet/config/NacosServiceListListenerRegisterer.java

@ -0,0 +1,161 @@
package com.epmet.config;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.listener.Event;
import com.alibaba.nacos.api.naming.listener.EventListener;
import com.alibaba.nacos.api.naming.listener.NamingEvent;
import com.alibaba.nacos.api.naming.pojo.ListView;
import com.epmet.commons.tools.exception.ExceptionUtils;
import com.netflix.loadbalancer.DynamicServerListLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
/**
* @author wxz
* @Description Nacos服务列表刷新监听注册器
* @date 2021.09.22 14:33:11
*/
@Slf4j
@Configuration
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery.serviceListChangedListening", name = "enable", havingValue = "true", matchIfMissing = false)
public class NacosServiceListListenerRegisterer {
public static final String REFRESH_SERVER_LIST_METHOD_NAME = "restOfInit";
// 服务列表拉取间隔:10s
public static final long SERVICE_LIST_PULLING_DELAY_SECONDS = 10;
private NamingService namingService;
private ScheduledExecutorService executor;
@Autowired
private NacosDiscoveryProperties discoveryProperties;
@Autowired
private SpringClientFactory springClientFactory;
// 监听中的服务列表
private List<String> observingServers = new ArrayList<>(33);
@PostConstruct
public void init() {
namingService = discoveryProperties.namingServiceInstance();
// 启动监听
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("NacosServiceListWatchingRegisterer");
return thread;
}
});
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS);
}
public class EpmetNacosServiceListListener implements Runnable {
@Override
public void run() {
doRefreshServerList();
}
/**
* @param
* @return
* @description 执行刷新
* @author wxz
* @date 2021.09.22 16:04:49
*/
private synchronized void doRefreshServerList() {
ListView<String> serviceListView = null;
try {
serviceListView = namingService.getServicesOfServer(1, 100);
//启动监听
if (serviceListView == null || serviceListView.getCount() == 0) {
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
return;
}
List<String> serviceList = serviceListView.getData();
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList);
for (String service : serviceList) {
try {
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
if (observingServers.contains(service)) {
continue;
}
namingService.subscribe(service, new EventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
NamingEvent namingEvent = (NamingEvent) event;
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances());
doRefreshServerList(service);
}
}
});
// 将该服务加入到监听列表中
observingServers.add(service);
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace);
}
}
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace);
}
}
/**
* @param serviceName
* @return
* @description 刷新ServerList
* @author wxz
* @date 2021.09.22 09:29:16
*/
private void doRefreshServerList(String serviceName) {
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
// try {
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
// restOfInitMethod.setAccessible(true);
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
// }
//}
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
// 暂且 1 try
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
if (loadBalancer instanceof DynamicServerListLoadBalancer) {
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer;
dslb.updateListOfServers();
}
}
}
}

4
epmet-module/epmet-point/epmet-point-server/src/main/resources/bootstrap.yml

@ -37,6 +37,9 @@ spring:
#不把自己注册到注册中心的地址
register-enabled: @nacos.register-enabled@
ip: @nacos.ip@
# 是否开启服务实例列表变更监听
serviceListChangedListening:
enable: @nacos.service-list-changed-listening.enable@
config:
enabled: @nacos.config-enabled@
server-addr: @nacos.server-addr@
@ -113,6 +116,7 @@ hystrix:
ribbon:
ReadTimeout: 300000
ConnectTimeout: 300000
# ServerListRefreshInterval: 5000
#pageHelper分页插件
pagehelper:

6
epmet-module/epmet-third/epmet-third-server/pom.xml

@ -197,6 +197,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
@ -236,6 +238,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>false</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
<!--钉钉 机器人地址-->
@ -274,6 +278,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>true</spring.flyway.enabled>
<!--测试钉钉 机器人地址-->

161
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<String> observingServers = new ArrayList<>(33);
@PostConstruct
public void init() {
namingService = discoveryProperties.namingServiceInstance();
// 启动监听
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("NacosServiceListWatchingRegisterer");
return thread;
}
});
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS);
}
public class EpmetNacosServiceListListener implements Runnable {
@Override
public void run() {
doRefreshServerList();
}
/**
* @param
* @return
* @description 执行刷新
* @author wxz
* @date 2021.09.22 16:04:49
*/
private synchronized void doRefreshServerList() {
ListView<String> serviceListView = null;
try {
serviceListView = namingService.getServicesOfServer(1, 100);
//启动监听
if (serviceListView == null || serviceListView.getCount() == 0) {
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
return;
}
List<String> serviceList = serviceListView.getData();
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList);
for (String service : serviceList) {
try {
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
if (observingServers.contains(service)) {
continue;
}
namingService.subscribe(service, new EventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
NamingEvent namingEvent = (NamingEvent) event;
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances());
doRefreshServerList(service);
}
}
});
// 将该服务加入到监听列表中
observingServers.add(service);
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace);
}
}
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace);
}
}
/**
* @param serviceName
* @return
* @description 刷新ServerList
* @author wxz
* @date 2021.09.22 09:29:16
*/
private void doRefreshServerList(String serviceName) {
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
// try {
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
// restOfInitMethod.setAccessible(true);
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
// }
//}
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
// 暂且 1 try
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
if (loadBalancer instanceof DynamicServerListLoadBalancer) {
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer;
dslb.updateListOfServers();
}
}
}
}

2
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@

6
epmet-module/gov-access/gov-access-server/pom.xml

@ -124,6 +124,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<!--flyway migration 数据库迁移工具-->
<spring.flyway.enabled>false</spring.flyway.enabled>
@ -161,6 +163,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>false</nacos.service-list-changed-listening.enable>
<!--flyway migration 数据库迁移工具-->
<spring.flyway.enabled>false</spring.flyway.enabled>
@ -198,6 +202,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<!--flyway migration 数据库迁移工具-->
<spring.flyway.enabled>true</spring.flyway.enabled>

161
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<String> observingServers = new ArrayList<>(33);
@PostConstruct
public void init() {
namingService = discoveryProperties.namingServiceInstance();
// 启动监听
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("NacosServiceListWatchingRegisterer");
return thread;
}
});
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS);
}
public class EpmetNacosServiceListListener implements Runnable {
@Override
public void run() {
doRefreshServerList();
}
/**
* @param
* @return
* @description 执行刷新
* @author wxz
* @date 2021.09.22 16:04:49
*/
private synchronized void doRefreshServerList() {
ListView<String> serviceListView = null;
try {
serviceListView = namingService.getServicesOfServer(1, 100);
//启动监听
if (serviceListView == null || serviceListView.getCount() == 0) {
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
return;
}
List<String> serviceList = serviceListView.getData();
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList);
for (String service : serviceList) {
try {
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
if (observingServers.contains(service)) {
continue;
}
namingService.subscribe(service, new EventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
NamingEvent namingEvent = (NamingEvent) event;
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances());
doRefreshServerList(service);
}
}
});
// 将该服务加入到监听列表中
observingServers.add(service);
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace);
}
}
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace);
}
}
/**
* @param serviceName
* @return
* @description 刷新ServerList
* @author wxz
* @date 2021.09.22 09:29:16
*/
private void doRefreshServerList(String serviceName) {
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
// try {
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
// restOfInitMethod.setAccessible(true);
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
// }
//}
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
// 暂且 1 try
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
if (loadBalancer instanceof DynamicServerListLoadBalancer) {
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer;
dslb.updateListOfServers();
}
}
}
}

2
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@

6
epmet-module/gov-grid/gov-grid-server/pom.xml

@ -116,6 +116,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
<!--钉钉 机器人地址-->
@ -148,6 +150,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>false</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
<!--钉钉 机器人地址-->
@ -180,6 +184,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>true</spring.flyway.enabled>
<!--测试钉钉 机器人地址-->

161
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<String> observingServers = new ArrayList<>(33);
@PostConstruct
public void init() {
namingService = discoveryProperties.namingServiceInstance();
// 启动监听
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("NacosServiceListWatchingRegisterer");
return thread;
}
});
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS);
}
public class EpmetNacosServiceListListener implements Runnable {
@Override
public void run() {
doRefreshServerList();
}
/**
* @param
* @return
* @description 执行刷新
* @author wxz
* @date 2021.09.22 16:04:49
*/
private synchronized void doRefreshServerList() {
ListView<String> serviceListView = null;
try {
serviceListView = namingService.getServicesOfServer(1, 100);
//启动监听
if (serviceListView == null || serviceListView.getCount() == 0) {
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
return;
}
List<String> serviceList = serviceListView.getData();
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList);
for (String service : serviceList) {
try {
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
if (observingServers.contains(service)) {
continue;
}
namingService.subscribe(service, new EventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
NamingEvent namingEvent = (NamingEvent) event;
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances());
doRefreshServerList(service);
}
}
});
// 将该服务加入到监听列表中
observingServers.add(service);
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace);
}
}
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace);
}
}
/**
* @param serviceName
* @return
* @description 刷新ServerList
* @author wxz
* @date 2021.09.22 09:29:16
*/
private void doRefreshServerList(String serviceName) {
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
// try {
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
// restOfInitMethod.setAccessible(true);
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
// }
//}
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
// 暂且 1 try
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
if (loadBalancer instanceof DynamicServerListLoadBalancer) {
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer;
dslb.updateListOfServers();
}
}
}
}

2
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@

6
epmet-module/gov-issue/gov-issue-server/pom.xml

@ -166,6 +166,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
<openapi.scan.server.url>https://epmet-dev.elinkservice.cn/api/epmetscan/api</openapi.scan.server.url>
@ -207,6 +209,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>false</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>false</spring.flyway.enabled>
<openapi.scan.server.url>https://epmet-dev.elinkservice.cn/api/epmetscan/api</openapi.scan.server.url>
@ -248,6 +252,8 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<spring.flyway.enabled>true</spring.flyway.enabled>
<openapi.scan.server.url>https://epmet-dev.elinkservice.cn/api/epmetscan/api</openapi.scan.server.url>

161
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<String> observingServers = new ArrayList<>(33);
@PostConstruct
public void init() {
namingService = discoveryProperties.namingServiceInstance();
// 启动监听
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("NacosServiceListWatchingRegisterer");
return thread;
}
});
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS);
}
public class EpmetNacosServiceListListener implements Runnable {
@Override
public void run() {
doRefreshServerList();
}
/**
* @param
* @return
* @description 执行刷新
* @author wxz
* @date 2021.09.22 16:04:49
*/
private synchronized void doRefreshServerList() {
ListView<String> serviceListView = null;
try {
serviceListView = namingService.getServicesOfServer(1, 100);
//启动监听
if (serviceListView == null || serviceListView.getCount() == 0) {
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
return;
}
List<String> serviceList = serviceListView.getData();
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList);
for (String service : serviceList) {
try {
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
if (observingServers.contains(service)) {
continue;
}
namingService.subscribe(service, new EventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
NamingEvent namingEvent = (NamingEvent) event;
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances());
doRefreshServerList(service);
}
}
});
// 将该服务加入到监听列表中
observingServers.add(service);
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace);
}
}
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace);
}
}
/**
* @param serviceName
* @return
* @description 刷新ServerList
* @author wxz
* @date 2021.09.22 09:29:16
*/
private void doRefreshServerList(String serviceName) {
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
// try {
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
// restOfInitMethod.setAccessible(true);
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
// }
//}
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
// 暂且 1 try
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
if (loadBalancer instanceof DynamicServerListLoadBalancer) {
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer;
dslb.updateListOfServers();
}
}
}
}

2
epmet-module/gov-issue/gov-issue-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@

9
epmet-module/gov-mine/gov-mine-server/pom.xml

@ -136,6 +136,9 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<!--钉钉 机器人地址-->
<dingTalk.robot.webHook>
https://oapi.dingtalk.com/robot/send?access_token=e894e5690f9d6a527722974c71548ff6c0fe29bd956589a09e21b16442a35ed4
@ -166,6 +169,9 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>false</nacos.service-list-changed-listening.enable>
<!--钉钉 机器人地址-->
<dingTalk.robot.webHook>
https://oapi.dingtalk.com/robot/send?access_token=e894e5690f9d6a527722974c71548ff6c0fe29bd956589a09e21b16442a35ed4
@ -196,6 +202,9 @@
<nacos.config.group></nacos.config.group>
<nacos.config-enabled>false</nacos.config-enabled>
<nacos.ip/>
<!--是否开启服务列表变更监听-->
<nacos.service-list-changed-listening.enable>true</nacos.service-list-changed-listening.enable>
<!--测试钉钉 机器人地址-->
<dingTalk.robot.webHook>
https://oapi.dingtalk.com/robot/send?access_token=e894e5690f9d6a527722974c71548ff6c0fe29bd956589a09e21b16442a35ed4

161
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<String> observingServers = new ArrayList<>(33);
@PostConstruct
public void init() {
namingService = discoveryProperties.namingServiceInstance();
// 启动监听
executor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("NacosServiceListWatchingRegisterer");
return thread;
}
});
// 立即启动,并15s刷新一次服务列表,用于新服务列表的发现
ScheduledFuture<?> future = executor.scheduleAtFixedRate(new EpmetNacosServiceListListener(), 0, SERVICE_LIST_PULLING_DELAY_SECONDS, TimeUnit.SECONDS);
}
public class EpmetNacosServiceListListener implements Runnable {
@Override
public void run() {
doRefreshServerList();
}
/**
* @param
* @return
* @description 执行刷新
* @author wxz
* @date 2021.09.22 16:04:49
*/
private synchronized void doRefreshServerList() {
ListView<String> serviceListView = null;
try {
serviceListView = namingService.getServicesOfServer(1, 100);
//启动监听
if (serviceListView == null || serviceListView.getCount() == 0) {
log.info("【Nacos服务列表定时刷新】当前无任何可添加监听的服务");
return;
}
List<String> serviceList = serviceListView.getData();
log.info("【Nacos服务列表定时刷新】Nacos服务端服务列表: {}", serviceList);
for (String service : serviceList) {
try {
// 如果该服务已经在监听列表中存在了,则不再注册监听。注:不能取消空服务的监听,因为空服务随时可能恢复运行,需要实时监听。
if (observingServers.contains(service)) {
continue;
}
namingService.subscribe(service, new EventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
NamingEvent namingEvent = (NamingEvent) event;
log.info("【Nacos服务列表刷新监听】收到事件:{}:[{}]", namingEvent.getServiceName(), namingEvent.getInstances());
doRefreshServerList(service);
}
}
});
// 将该服务加入到监听列表中
observingServers.add(service);
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】订阅ApplicationContext的刷新事件失败,错误信息:{}", errorStackTrace);
}
}
} catch (NacosException e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
log.error("【Nacos服务列表定时刷新】链接Nacos服务端失败,错误信息:{}", errorStackTrace);
}
}
/**
* @param serviceName
* @return
* @description 刷新ServerList
* @author wxz
* @date 2021.09.22 09:29:16
*/
private void doRefreshServerList(String serviceName) {
// 刷新方式1:反射调用DynamicServerListLoadBalancer中的restOfInit()方法。该方法原来只执行一次,此处不推荐用
//ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
//if (loadBalancer instanceof ZoneAwareLoadBalancer) {
// ZoneAwareLoadBalancer zaLoadBalancer = (ZoneAwareLoadBalancer) loadBalancer;
// IClientConfig clientConfig = springClientFactory.getClientConfig(serviceName);
// try {
// Method restOfInitMethod = zaLoadBalancer.getClass().getSuperclass().getDeclaredMethod(REFRESH_SERVER_LIST_METHOD_NAME, IClientConfig.class);
// restOfInitMethod.setAccessible(true);
// restOfInitMethod.invoke(zaLoadBalancer, clientConfig);
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
// log.error("【LoadBalancer刷新服务列表】失败:{}", errorStackTrace);
// }
//}
// 刷新方式2:DynamicServerListLoadBalancer#updateListOfServers()该方法为ribbon定时刷新服务列表的时候真正调用的方法,但是加了@VisibleForTesting
// 暂且 1 try
ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer(serviceName);
if (loadBalancer instanceof DynamicServerListLoadBalancer) {
DynamicServerListLoadBalancer dslb = (DynamicServerListLoadBalancer) loadBalancer;
dslb.updateListOfServers();
}
}
}
}

2
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@

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save