|
|
|
@ -6,16 +6,15 @@ import com.alibaba.nacos.api.naming.NamingService; |
|
|
|
|
import com.alibaba.nacos.api.naming.pojo.Instance; |
|
|
|
|
import com.alibaba.nacos.api.naming.pojo.ListView; |
|
|
|
|
import com.gitee.sop.gatewaycommon.bean.InstanceDefinition; |
|
|
|
|
import lombok.AllArgsConstructor; |
|
|
|
|
import lombok.Data; |
|
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired; |
|
|
|
|
import org.springframework.context.ApplicationEvent; |
|
|
|
|
import org.springframework.util.CollectionUtils; |
|
|
|
|
|
|
|
|
|
import java.util.Collections; |
|
|
|
|
import java.util.Comparator; |
|
|
|
|
import java.util.HashSet; |
|
|
|
|
import java.util.List; |
|
|
|
|
import java.util.Map; |
|
|
|
|
import java.util.Objects; |
|
|
|
|
import java.util.Set; |
|
|
|
|
import java.util.stream.Collectors; |
|
|
|
@ -28,7 +27,9 @@ import java.util.stream.Collectors; |
|
|
|
|
@Slf4j |
|
|
|
|
public class NacosRegistryListener extends BaseRegistryListener { |
|
|
|
|
|
|
|
|
|
private volatile Set<String> cacheServices = new HashSet<>(); |
|
|
|
|
private static final String METADATA_KEY_TIME_STARTUP = "time.startup"; |
|
|
|
|
|
|
|
|
|
private volatile Set<NacosServiceHolder> cacheServices = new HashSet<>(); |
|
|
|
|
|
|
|
|
|
@Autowired |
|
|
|
|
private NacosDiscoveryProperties nacosDiscoveryProperties; |
|
|
|
@ -38,6 +39,41 @@ public class NacosRegistryListener extends BaseRegistryListener { |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public synchronized void onEvent(ApplicationEvent applicationEvent) { |
|
|
|
|
List<NacosServiceHolder> serviceList = this.getServiceList(); |
|
|
|
|
final Set<NacosServiceHolder> currentServices = new HashSet<>(serviceList); |
|
|
|
|
|
|
|
|
|
// 删除现有的,剩下的就是新服务
|
|
|
|
|
currentServices.removeAll(cacheServices); |
|
|
|
|
// 如果有新的服务注册进来
|
|
|
|
|
if (currentServices.size() > 0) { |
|
|
|
|
currentServices.forEach(nacosServiceHolder -> { |
|
|
|
|
Instance instance = nacosServiceHolder.getInstance(); |
|
|
|
|
InstanceDefinition instanceDefinition = new InstanceDefinition(); |
|
|
|
|
instanceDefinition.setInstanceId(instance.getInstanceId()); |
|
|
|
|
instanceDefinition.setServiceId(nacosServiceHolder.getServiceId()); |
|
|
|
|
instanceDefinition.setIp(instance.getIp()); |
|
|
|
|
instanceDefinition.setPort(instance.getPort()); |
|
|
|
|
instanceDefinition.setMetadata(instance.getMetadata()); |
|
|
|
|
pullRoutes(instanceDefinition); |
|
|
|
|
if (registryEventList != null) { |
|
|
|
|
registryEventList.forEach(registryEvent -> registryEvent.onRegistry(instanceDefinition)); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 如果有服务下线
|
|
|
|
|
Set<String> removedServiceIdList = getRemovedServiceId(serviceList); |
|
|
|
|
// 移除
|
|
|
|
|
this.doRemove(removedServiceIdList); |
|
|
|
|
|
|
|
|
|
cacheServices = new HashSet<>(serviceList); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 获取建康的服务实例 |
|
|
|
|
* @return 没有返回空的list |
|
|
|
|
*/ |
|
|
|
|
private List<NacosServiceHolder> getServiceList() { |
|
|
|
|
NamingService namingService = nacosDiscoveryProperties.namingServiceInstance(); |
|
|
|
|
ListView<String> servicesOfServer = null; |
|
|
|
|
try { |
|
|
|
@ -46,67 +82,42 @@ public class NacosRegistryListener extends BaseRegistryListener { |
|
|
|
|
log.error("namingService.getServicesOfServer()错误", e); |
|
|
|
|
} |
|
|
|
|
if (servicesOfServer == null || CollectionUtils.isEmpty(servicesOfServer.getData())) { |
|
|
|
|
return; |
|
|
|
|
return Collections.emptyList(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Map<String, Instance> instanceMap = servicesOfServer |
|
|
|
|
return servicesOfServer |
|
|
|
|
.getData() |
|
|
|
|
.stream() |
|
|
|
|
.filter(this::canOperator) |
|
|
|
|
.map(serviceName -> { |
|
|
|
|
try { |
|
|
|
|
// 获取服务实例
|
|
|
|
|
List<Instance> allInstances = namingService.getAllInstances(serviceName); |
|
|
|
|
if (CollectionUtils.isEmpty(allInstances)) { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
Instance instance = allInstances.stream() |
|
|
|
|
// 只获取建康实例
|
|
|
|
|
.filter(Instance::isHealthy) |
|
|
|
|
.findFirst() |
|
|
|
|
// 根据启动时间倒叙,找到最新的服务器
|
|
|
|
|
.max(Comparator.comparing(ins -> { |
|
|
|
|
String startupTime = ins.getMetadata().getOrDefault(METADATA_KEY_TIME_STARTUP, "0"); |
|
|
|
|
return Long.valueOf(startupTime); |
|
|
|
|
})) |
|
|
|
|
.orElse(null); |
|
|
|
|
return instance == null ? null : new InstanceInfo(serviceName, instance); |
|
|
|
|
if (instance == null) { |
|
|
|
|
return null; |
|
|
|
|
} else { |
|
|
|
|
String startupTime = instance.getMetadata().getOrDefault("time.startup", "0"); |
|
|
|
|
long time = Long.parseLong(startupTime); |
|
|
|
|
return new NacosServiceHolder(serviceName, time, instance); |
|
|
|
|
} |
|
|
|
|
} catch (NacosException e) { |
|
|
|
|
log.error("namingService.getAllInstances(serviceName)错误,serviceName:{}", serviceName, e); |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
.filter(Objects::nonNull) |
|
|
|
|
.collect(Collectors.toMap(InstanceInfo::getServiceName, InstanceInfo::getInstance)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Set<String> serviceNames = instanceMap.keySet(); |
|
|
|
|
|
|
|
|
|
final Set<String> currentServices = new HashSet<>(serviceNames); |
|
|
|
|
// 删除现有的,剩下的就是新服务
|
|
|
|
|
currentServices.removeAll(cacheServices); |
|
|
|
|
// 如果有新的服务注册进来
|
|
|
|
|
if (currentServices.size() > 0) { |
|
|
|
|
currentServices.forEach(serviceName -> { |
|
|
|
|
Instance instance = instanceMap.get(serviceName); |
|
|
|
|
InstanceDefinition instanceDefinition = new InstanceDefinition(); |
|
|
|
|
instanceDefinition.setInstanceId(instance.getInstanceId()); |
|
|
|
|
instanceDefinition.setServiceId(serviceName); |
|
|
|
|
instanceDefinition.setIp(instance.getIp()); |
|
|
|
|
instanceDefinition.setPort(instance.getPort()); |
|
|
|
|
instanceDefinition.setMetadata(instance.getMetadata()); |
|
|
|
|
pullRoutes(instanceDefinition); |
|
|
|
|
if (registryEventList != null) { |
|
|
|
|
registryEventList.forEach(registryEvent -> registryEvent.onRegistry(instanceDefinition)); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 如果有服务删除
|
|
|
|
|
Set<String> removedServiceIdList = getRemovedServiceId(serviceNames); |
|
|
|
|
if (removedServiceIdList.size() > 0) { |
|
|
|
|
removedServiceIdList.forEach(serviceId->{ |
|
|
|
|
this.removeRoutes(serviceId); |
|
|
|
|
if (registryEventList != null) { |
|
|
|
|
registryEventList.forEach(registryEvent -> registryEvent.onRemove(serviceId)); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
cacheServices = new HashSet<>(serviceNames); |
|
|
|
|
.collect(Collectors.toList()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -115,18 +126,29 @@ public class NacosRegistryListener extends BaseRegistryListener { |
|
|
|
|
* @param serviceList 最新的serviceId集合 |
|
|
|
|
* @return 返回已下线的serviceId |
|
|
|
|
*/ |
|
|
|
|
private Set<String> getRemovedServiceId(Set<String> serviceList) { |
|
|
|
|
Set<String> cache = cacheServices; |
|
|
|
|
// 删除最新的,剩下就是已经删除的
|
|
|
|
|
cache.removeAll(serviceList); |
|
|
|
|
private Set<String> getRemovedServiceId(List<NacosServiceHolder> serviceList) { |
|
|
|
|
Set<String> cache = cacheServices.stream() |
|
|
|
|
.map(NacosServiceHolder::getServiceId) |
|
|
|
|
.collect(Collectors.toSet()); |
|
|
|
|
|
|
|
|
|
Set<String> newList = serviceList.stream() |
|
|
|
|
.map(NacosServiceHolder::getServiceId) |
|
|
|
|
.collect(Collectors.toSet()); |
|
|
|
|
|
|
|
|
|
cache.removeAll(newList); |
|
|
|
|
return cache; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Data |
|
|
|
|
@AllArgsConstructor |
|
|
|
|
private static class InstanceInfo { |
|
|
|
|
private String serviceName; |
|
|
|
|
private Instance instance; |
|
|
|
|
private void doRemove(Set<String> deletedServices) { |
|
|
|
|
if (deletedServices == null) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
deletedServices.forEach(serviceId -> { |
|
|
|
|
this.removeRoutes(serviceId); |
|
|
|
|
if (registryEventList != null) { |
|
|
|
|
registryEventList.forEach(registryEvent -> registryEvent.onRemove(serviceId)); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|