当前位置:   article > 正文

【Nacos】微服务注册在不同的group上,支持跨group服务发现,二次开发

【Nacos】微服务注册在不同的group上,支持跨group服务发现,二次开发

        Nacos具备微服务注册和发现,以及配置管理的功能,本文详情描述【注册和发现】的原理,以及基本使用,包括如何进行跨group注册和发现。

一、Nacos配置
  1. spring:
  2. cloud:
  3. nacos:
  4. discovery:
  5. server-addr: nacosIP地址:8849
  6. namespace: dev
  7. group: Product
  8. config:
  9. server-addr: nacosIP地址:8849
  10. namespace: dev
  11. group: Product
  12. file-extension: yaml
  13. refresh-enabled: true
  14. enable-remote-sync-config: true
  15. name: product.yaml
  1. spring:
  2. cloud:
  3. nacos:
  4. discovery:
  5. server-addr: nacosIP地址:8849
  6. namespace: dev
  7. group: Order
  8. config:
  9. server-addr: nacosIP地址:8849
  10. namespace: dev
  11. group: Order
  12. file-extension: yaml
  13. refresh-enabled: true
  14. enable-remote-sync-config: true
  15. name: order.yaml
  16. extension-configs:
  17. - data-id: config-global.yaml
  18. group: Order
  19. refresh: true
一、NacosServiceDiscovery 中 getInstances 获取注册在nacos上的服务实例清单
  1. public List<ServiceInstance> getInstances(String serviceId) throws NacosException {
  2. String group = this.discoveryProperties.getGroup();
  3. List<Instance> instances = this.namingService().selectInstances(serviceId, group, true);
  4. return hostToServiceInstanceList(instances, serviceId);
  5. }

  但是原始功能不支持跨group服务发现,所以我们需要重写 getInstances方法。

二、NacosServiceDiscoveryV2 继承 NacosServiceDiscovery,并重写 getInstances

  1. import com.alibaba.cloud.nacos.NacosServiceInstance;
  2. import com.alibaba.cloud.nacos.NacosServiceManager;
  3. import com.alibaba.cloud.nacos.discovery.NacosServiceDiscovery;
  4. import com.alibaba.nacos.api.exception.NacosException;
  5. import com.alibaba.nacos.api.naming.NamingService;
  6. import com.alibaba.nacos.api.naming.pojo.Instance;
  7. import com.alibaba.nacos.api.naming.pojo.ListView;
  8. import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
  9. import org.springframework.cloud.client.ServiceInstance;
  10. import java.util.*;
  11. import static com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty;
  12. import static java.util.Objects.isNull;
  13. /**
  14. * @description: naocs服务发现重写
  15. */
  16. public class NacosServiceDiscoveryV2 extends NacosServiceDiscovery {
  17. private final NacosDiscoveryPropertiesV2 discoveryProperties;
  18. private final NacosShareProperties nacosShareProperties;
  19. private final NacosServiceManager nacosServiceManager;
  20. public NacosServiceDiscoveryV2(NacosDiscoveryPropertiesV2 discoveryProperties, NacosShareProperties nacosShareProperties, NacosServiceManager nacosServiceManager) {
  21. super(discoveryProperties, nacosServiceManager);
  22. this.discoveryProperties = discoveryProperties;
  23. this.nacosShareProperties = nacosShareProperties;
  24. this.nacosServiceManager = nacosServiceManager;
  25. }
  26. /**
  27. * Return all instances for the given service.
  28. * @param serviceId id of service
  29. * @return list of instances
  30. * @throws NacosException nacosException
  31. */
  32. @Override
  33. public List<ServiceInstance> getInstances(String serviceId) throws NacosException {
  34. String group = discoveryProperties.getGroup();
  35. List<Instance> instances = discoveryProperties.namingServiceInstance()
  36. .selectInstances(serviceId, group, true);
  37. if (isEmpty(instances)) {
  38. Map<String, Set<String>> namespaceGroupMap = nacosShareProperties.getNamespaceGroupMap();
  39. Map<String, NamingService> namespace2NamingServiceMap = discoveryProperties.shareNamingServiceInstances();
  40. for (Map.Entry<String, NamingService> entry : namespace2NamingServiceMap.entrySet()) {
  41. String namespace;
  42. NamingService namingService;
  43. if (isNull(namespace = entry.getKey()) || isNull(namingService = entry.getValue()))
  44. continue;
  45. Set<String> groupNames = namespaceGroupMap.get(namespace);
  46. List<Instance> shareInstances;
  47. if (isEmpty(groupNames)) {
  48. shareInstances = namingService.selectInstances(serviceId, group, true);
  49. if (CollectionUtils.isNotEmpty(shareInstances))
  50. break;
  51. } else {
  52. shareInstances = new ArrayList<>();
  53. for (String groupName : groupNames) {
  54. List<Instance> subShareInstances = namingService.selectInstances(serviceId, groupName, true);
  55. if (CollectionUtils.isNotEmpty(subShareInstances)) {
  56. shareInstances.addAll(subShareInstances);
  57. }
  58. }
  59. }
  60. if (CollectionUtils.isNotEmpty(shareInstances)) {
  61. instances = shareInstances;
  62. break;
  63. }
  64. }
  65. }
  66. return hostToServiceInstanceList(instances, serviceId);
  67. }
  68. /**
  69. * Return the names of all services.
  70. * @return list of service names
  71. * @throws NacosException nacosException
  72. */
  73. public List<String> getServices() throws NacosException {
  74. String group = discoveryProperties.getGroup();
  75. ListView<String> services = discoveryProperties.namingServiceInstance()
  76. .getServicesOfServer(1, Integer.MAX_VALUE, group);
  77. return services.getData();
  78. }
  79. public static List<ServiceInstance> hostToServiceInstanceList(
  80. List<Instance> instances, String serviceId) {
  81. List<ServiceInstance> result = new ArrayList<>(instances.size());
  82. for (Instance instance : instances) {
  83. ServiceInstance serviceInstance = hostToServiceInstance(instance, serviceId);
  84. if (serviceInstance != null) {
  85. result.add(serviceInstance);
  86. }
  87. }
  88. return result;
  89. }
  90. public static ServiceInstance hostToServiceInstance(Instance instance,
  91. String serviceId) {
  92. if (instance == null || !instance.isEnabled() || !instance.isHealthy()) {
  93. return null;
  94. }
  95. NacosServiceInstance nacosServiceInstance = new NacosServiceInstance();
  96. nacosServiceInstance.setHost(instance.getIp());
  97. nacosServiceInstance.setPort(instance.getPort());
  98. nacosServiceInstance.setServiceId(serviceId);
  99. Map<String, String> metadata = new HashMap<>();
  100. metadata.put("nacos.instanceId", instance.getInstanceId());
  101. metadata.put("nacos.weight", instance.getWeight() + "");
  102. metadata.put("nacos.healthy", instance.isHealthy() + "");
  103. metadata.put("nacos.cluster", instance.getClusterName() + "");
  104. metadata.putAll(instance.getMetadata());
  105. nacosServiceInstance.setMetadata(metadata);
  106. if (metadata.containsKey("secure")) {
  107. boolean secure = Boolean.parseBoolean(metadata.get("secure"));
  108. nacosServiceInstance.setSecure(secure);
  109. }
  110. return nacosServiceInstance;
  111. }
  112. private NamingService namingService() {
  113. return nacosServiceManager
  114. .getNamingService(discoveryProperties.getNacosProperties());
  115. }
  116. }

原理:

1、根据 serviceId 和 group 获取当前实例

2、获取所有group清单,并根据group找到group下所有实例

3、将group清单,加入到自己的实例清单中。

三、NacosDiscoveryPropertiesV2 继承 NacosDiscoveryProperties,服务发现属性重写 shareNamingServiceInstances、getNacosProperties方法

  1. import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
  2. import com.alibaba.nacos.api.NacosFactory;
  3. import com.alibaba.nacos.api.naming.NamingService;
  4. import com.alibaba.nacos.client.naming.utils.UtilAndComs;
  5. import org.slf4j.Logger;
  6. import org.slf4j.LoggerFactory;
  7. import java.util.*;
  8. import java.util.concurrent.ConcurrentHashMap;
  9. import java.util.function.Function;
  10. import java.util.function.Predicate;
  11. import static com.alibaba.nacos.api.PropertyKeyConst.*;
  12. import static java.util.Objects.nonNull;
  13. /**
  14. * @description: naocs服务发现属性重写
  15. */
  16. public class NacosDiscoveryPropertiesV2 extends NacosDiscoveryProperties {
  17. private static final Logger log = LoggerFactory.getLogger(NacosDiscoveryPropertiesV2.class);
  18. private final NacosShareProperties nacosShareProperties;
  19. private static final Map<String, NamingService> NAMESPACE_TO_NAMING_SERVICE_MAP = new ConcurrentHashMap<>();
  20. public NacosDiscoveryPropertiesV2(NacosShareProperties nacosShareProperties) {
  21. super();
  22. this.nacosShareProperties = nacosShareProperties;
  23. }
  24. public Map<String, NamingService> shareNamingServiceInstances() {
  25. if (!NAMESPACE_TO_NAMING_SERVICE_MAP.isEmpty()) {
  26. return new HashMap<>(NAMESPACE_TO_NAMING_SERVICE_MAP);
  27. }
  28. List<NacosShareProperties.NacosShareEntity> entities = Optional.ofNullable(nacosShareProperties)
  29. .map(NacosShareProperties::getEntities).orElse(Collections.emptyList());
  30. entities.stream().filter(entity -> nonNull(entity) && nonNull(entity.getNamespace()))
  31. .filter(distinctByKey(NacosShareProperties.NacosShareEntity::getNamespace))
  32. .forEach(entity -> {
  33. try {
  34. NamingService namingService = NacosFactory.createNamingService(getNacosProperties(entity.getNamespace()));
  35. if (namingService != null) {
  36. NAMESPACE_TO_NAMING_SERVICE_MAP.put(entity.getNamespace(), namingService);
  37. }
  38. } catch (Exception e) {
  39. log.error("create naming service error! properties={}, e=", this, e);
  40. }
  41. });
  42. return new HashMap<>(NAMESPACE_TO_NAMING_SERVICE_MAP);
  43. }
  44. private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
  45. Map<Object, Boolean> seen = new ConcurrentHashMap<>();
  46. return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
  47. }
  48. private Properties getNacosProperties(String namespace) {
  49. Properties properties = new Properties();
  50. properties.put(SERVER_ADDR, getServerAddr());
  51. properties.put(USERNAME, Objects.toString(getUsername(), ""));
  52. properties.put(PASSWORD, Objects.toString(getPassword(), ""));
  53. properties.put(NAMESPACE, namespace);
  54. properties.put(UtilAndComs.NACOS_NAMING_LOG_NAME, getLogName());
  55. String endpoint = getEndpoint();
  56. if (endpoint.contains(":")) {
  57. int index = endpoint.indexOf(":");
  58. properties.put(ENDPOINT, endpoint.substring(0, index));
  59. properties.put(ENDPOINT_PORT, endpoint.substring(index + 1));
  60. }
  61. else {
  62. properties.put(ENDPOINT, endpoint);
  63. }
  64. properties.put(ACCESS_KEY, getAccessKey());
  65. properties.put(SECRET_KEY, getSecretKey());
  66. properties.put(CLUSTER_NAME, getClusterName());
  67. properties.put(NAMING_LOAD_CACHE_AT_START, getNamingLoadCacheAtStart());
  68. // enrichNacosDiscoveryProperties(properties);
  69. return properties;
  70. }
  71. }

四、共享share属性类 NacosShareProperties

  1. import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
  2. import org.springframework.boot.context.properties.ConfigurationProperties;
  3. import org.springframework.context.annotation.Configuration;
  4. import java.util.*;
  5. import java.util.concurrent.ConcurrentHashMap;
  6. import static java.util.Objects.nonNull;
  7. /**
  8. * <pre>
  9. * @description: 共享nacos属性
  10. * </pre>
  11. */
  12. @Configuration
  13. @ConfigurationProperties(prefix = "nacos.share")
  14. public class NacosShareProperties {
  15. private final Map<String, Set<String>> NAMESPACE_TO_GROUP_NAME_MAP = new ConcurrentHashMap<>();
  16. /**
  17. * 共享nacos实体列表
  18. */
  19. private List<NacosShareEntity> entities;
  20. public List<NacosShareEntity> getEntities() {
  21. return entities;
  22. }
  23. public void setEntities(List<NacosShareEntity> entities) {
  24. this.entities = entities;
  25. }
  26. public Map<String, Set<String>> getNamespaceGroupMap() {
  27. if (CollectionUtils.isEmpty(entities)) {
  28. return new HashMap<>();
  29. }
  30. entities.stream().filter(entity -> nonNull(entity) && nonNull(entity.getNamespace()))
  31. .forEach(entity -> {
  32. Set<String> groupNames = NAMESPACE_TO_GROUP_NAME_MAP.computeIfAbsent(entity.getNamespace(), k -> new HashSet<>());
  33. if (nonNull(entity.getGroupNames()))
  34. groupNames.addAll(entity.getGroupNames());
  35. });
  36. return new HashMap<>(NAMESPACE_TO_GROUP_NAME_MAP);
  37. }
  38. @Override
  39. public String toString() {
  40. return "NacosShareProperties{" +
  41. "entities=" + entities +
  42. '}';
  43. }
  44. /**
  45. * 共享nacos实体
  46. */
  47. public static final class NacosShareEntity {
  48. /**
  49. * 命名空间
  50. */
  51. private String namespace;
  52. /**
  53. * 分组
  54. */
  55. private List<String> groupNames;
  56. public String getNamespace() {
  57. return namespace;
  58. }
  59. public void setNamespace(String namespace) {
  60. this.namespace = namespace;
  61. }
  62. public List<String> getGroupNames() {
  63. return groupNames;
  64. }
  65. public void setGroupNames(List<String> groupNames) {
  66. this.groupNames = groupNames;
  67. }
  68. @Override
  69. public String toString() {
  70. return "NacosShareEntity{" +
  71. "namespace='" + namespace + '\'' +
  72. ", groupNames=" + groupNames +
  73. '}';
  74. }
  75. }
  76. }

五、整合配置类 NacosDiscoveryAutoConfigurationV2

  1. import com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled;
  2. import com.alibaba.cloud.nacos.NacosServiceManager;
  3. import com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration;
  4. import com.alibaba.cloud.nacos.discovery.NacosServiceDiscovery;
  5. import org.springframework.boot.autoconfigure.AutoConfigureBefore;
  6. import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
  7. import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
  8. import org.springframework.context.annotation.Bean;
  9. import org.springframework.context.annotation.Configuration;
  10. /**
  11. * @Auther: yangjian
  12. */
  13. @Configuration(proxyBeanMethods = false)
  14. @ConditionalOnDiscoveryEnabled
  15. @ConditionalOnNacosDiscoveryEnabled
  16. @AutoConfigureBefore({NacosDiscoveryAutoConfiguration.class})
  17. public class NacosDiscoveryAutoConfigurationV2 {
  18. @Bean
  19. @ConditionalOnMissingBean
  20. public NacosDiscoveryPropertiesV2 nacosProperties(NacosShareProperties nacosShareProperties) {
  21. return new NacosDiscoveryPropertiesV2(nacosShareProperties);
  22. }
  23. @Bean
  24. @ConditionalOnMissingBean
  25. public NacosServiceDiscovery nacosServiceDiscovery(NacosDiscoveryPropertiesV2 discoveryPropertiesV2
  26. , NacosShareProperties nacosShareProperties, NacosServiceManager nacosServiceManager) {
  27. return new NacosServiceDiscoveryV2(discoveryPropertiesV2, nacosShareProperties, nacosServiceManager);
  28. }
  29. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/902006
推荐阅读
相关标签
  

闽ICP备14008679号