一、問題背景
在開發(fā)某個(gè)公共應(yīng)用時(shí),筆者發(fā)現(xiàn)該公共應(yīng)用的數(shù)據(jù)是所有測試環(huán)境(假設(shè)存在 dev/dev2/dev3)通用的。
這就意味著只需部署一個(gè)應(yīng)用,就能滿足所有測試環(huán)境的需求;也意味著所有測試環(huán)境都需要調(diào)用該公共應(yīng)用,而不同測試環(huán)境的應(yīng)用注冊在不同的 Nacos 命名空間。
二、兩種解決方案
如果所有測試環(huán)境都需要調(diào)用該公共應(yīng)用,有兩種可行的方案。第一種,將該公共服務(wù)同時(shí)注冊到不同的測試環(huán)境所對應(yīng)的命名空間中。
第二種,將公共應(yīng)用注冊到單獨(dú)的命名空間,不同的測試環(huán)境能夠跨命名空間訪問該應(yīng)用。
三、詳細(xì)的問題解決過程
先行交代筆者的版本號(hào)配置。Nacos 客戶端版本號(hào)為 NACOS 1.4.1
;Java 項(xiàng)目的 Nacos 版本號(hào)如下。
最初想法是將該公共應(yīng)用同時(shí)注冊到多個(gè)命名空間下。
01 注冊多個(gè)命名空間
從該博客中,我們看到其他程序員朋友也遇到了類似的公共服務(wù)的需求。在本篇文章中,筆者將進(jìn)一步分享實(shí)現(xiàn)思路以及示例代碼。
說明:以下代碼內(nèi)容來自用戶 chuntaojun 的分享。
shareNamespace={namespaceId[:group]},{namespaceId[:group]}
復(fù)制代碼
@RunWith(SpringRunner.class)
@SpringBootTest(classes?=?NamingApp.class,?properties?=?{"server.servlet.context-path=/nacos"},
????webEnvironment?=?SpringBootTest.WebEnvironment.RANDOM_PORT)
public?class?SelectServiceInShareNamespace_ITCase?{
????private?NamingService?naming1;
????private?NamingService?naming2;
????@LocalServerPort
????private?int?port;
????@Before
????public?void?init()?throws?Exception{
????????NamingBase.prepareServer(port);
????????if?(naming1?==?null)?{
????????????Properties?properties?=?new?Properties();
????????????properties.setProperty(PropertyKeyConst.SERVER_ADDR,?"127.0.0.1"+":"+port);
????????????properties.setProperty(PropertyKeyConst.SHARE_NAMESPACE,?"57425802-3058-4507-9a73-3229b9f00a36");
????????????naming1?=?NamingFactory.createNamingService(properties);
????????????Properties?properties2?=?new?Properties();
????????????properties2.setProperty(PropertyKeyConst.SERVER_ADDR,?"127.0.0.1"+":"+port);
????????????properties2.setProperty(PropertyKeyConst.NAMESPACE,?"57425802-3058-4507-9a73-3229b9f00a36");
????????????naming2?=?NamingFactory.createNamingService(properties2);
????????}
????????while?(true)?{
????????????if?(!"UP".equals(naming1.getServerStatus()))?{
????????????????Thread.sleep(1000L);
????????????????continue;
????????????}
????????????break;
????????}
????}
????@Test
????public?void?testSelectInstanceInShareNamespaceNoGroup()?throws?NacosException,?InterruptedException?{
????????String?service1?=?randomDomainName();
????????String?service2?=?randomDomainName();
????????naming1.registerInstance(service1,?"127.0.0.1",?90);
????????naming2.registerInstance(service2,?"127.0.0.2",?90);
????????Thread.sleep(1000);
????????List<Instance>?instances?=?naming1.getAllInstances(service2);
????????Assert.assertEquals(1,?instances.size());
????????Assert.assertEquals(service2,?NamingUtils.getServiceName(instances.get(0).getServiceName()));
????}
????@Test
????public?void?testSelectInstanceInShareNamespaceWithGroup()?throws?NacosException,?InterruptedException?{
????????String?service1?=?randomDomainName();
????????String?service2?=?randomDomainName();
????????naming2.registerInstance(service1,?groupName,?"127.0.0.1",?90);
????????naming3.registerInstance(service2,?"127.0.0.2",?90);
????????Thread.sleep(1000);
????????List<Instance>?instances?=?naming3.getAllInstances(service1);
????????Assert.assertEquals(1,?instances.size());
????????Assert.assertEquals(service1,?NamingUtils.getServiceName(instances.get(0).getServiceName()));
????????Assert.assertEquals(groupName,?NamingUtils.getServiceName(NamingUtils.getGroupName(instances.get(0).getServiceName())));
????}
}
復(fù)制代碼
進(jìn)一步考慮后發(fā)現(xiàn)該解決方案可能不太契合當(dāng)前遇到的問題。公司目前的開發(fā)測試環(huán)境有很多個(gè),并且不確定以后會(huì)不會(huì)繼續(xù)增加。
如果每增加一個(gè)環(huán)境,都需要修改一次公共服務(wù)的配置,并且重啟一次公共服務(wù),著實(shí)太麻煩了。倒不如反其道而行,讓其他的服務(wù)器實(shí)現(xiàn)跨命名空間訪問公共服務(wù)。
02 跨命名空間訪問
針對實(shí)際問題查找資料時(shí),我們找到了類似的參考分享《重寫 Nacos 服務(wù)發(fā)現(xiàn)邏輯動(dòng)態(tài)修改遠(yuǎn)程服務(wù)IP地址》。
跟著博客思路看代碼,筆者了解到服務(wù)發(fā)現(xiàn)的主要相關(guān)類是 NacosNamingService
, NacosDiscoveryProperties
, NacosDiscoveryAutoConfiguration
。
然后,筆者將博客的示例代碼復(fù)制過來,試著進(jìn)行如下調(diào)試:
@Slf4j
@Configuration
@ConditionalOnNacosDiscoveryEnabled
@ConditionalOnProperty(
????????name?=?{"spring.profiles.active"},
????????havingValue?=?"dev"
)
@AutoConfigureBefore({NacosDiscoveryClientAutoConfiguration.class})
public?class?DevEnvironmentNacosDiscoveryClient?{
????@Bean
????@ConditionalOnMissingBean
????public?NacosDiscoveryProperties?nacosProperties()?{
????????return?new?DevEnvironmentNacosDiscoveryProperties();
????}
????static?class?DevEnvironmentNacosDiscoveryProperties?extends?NacosDiscoveryProperties?{
????????private?NamingService?namingService;
????????@Override
????????public?NamingService?namingServiceInstance()?{
????????????if?(null?!=?this.namingService)?{
????????????????return?this.namingService;
????????????}?else?{
????????????????Properties?properties?=?new?Properties();
????????????????properties.put("serverAddr",?super.getServerAddr());
????????????????properties.put("namespace",?super.getNamespace());
????????????????properties.put("com.alibaba.nacos.naming.log.filename",?super.getLogName());
????????????????if?(super.getEndpoint().contains(":"))?{
????????????????????int?index?=?super.getEndpoint().indexOf(":");
????????????????????properties.put("endpoint",?super.getEndpoint().substring(0,?index));
????????????????????properties.put("endpointPort",?super.getEndpoint().substring(index?+?1));
????????????????}?else?{
????????????????????properties.put("endpoint",?super.getEndpoint());
????????????????}
????????????????properties.put("accessKey",?super.getAccessKey());
????????????????properties.put("secretKey",?super.getSecretKey());
????????????????properties.put("clusterName",?super.getClusterName());
????????????????properties.put("namingLoadCacheAtStart",?super.getNamingLoadCacheAtStart());
????????????????try?{
????????????????????this.namingService?=?new?DevEnvironmentNacosNamingService(properties);
????????????????}?catch?(Exception?var3)?{
????????????????????log.error("create?naming?service?error!properties={},e=,",?this,?var3);
????????????????????return?null;
????????????????}
????????????????return?this.namingService;
????????????}
????????}
????}
????static?class?DevEnvironmentNacosNamingService?extends?NacosNamingService?{
????????public?DevEnvironmentNacosNamingService(Properties?properties)?{
????????????super(properties);
????????}
????????@Override
????????public?List<Instance>?selectInstances(String?serviceName,?List<String>?clusters,?boolean?healthy)?throws?NacosException?{
????????????List<Instance>?instances?=?super.selectInstances(serviceName,?clusters,?healthy);
????????????instances.stream().forEach(instance?->?instance.setIp("10.101.232.24"));
????????????return?instances;
????????}
????}
}
復(fù)制代碼
調(diào)試后發(fā)現(xiàn)博客提供的代碼并不能滿足筆者的需求,還得進(jìn)一步深入探索。
但幸運(yùn)的是,調(diào)試過程發(fā)現(xiàn) Nacos 服務(wù)發(fā)現(xiàn)的關(guān)鍵類是 com.alibaba.cloud.nacos.discovery.NacosServiceDiscovery
,其中的關(guān)鍵方法是 getInstances()
和 getServices()
,即「返回指定服務(wù) ID 的所有服務(wù)實(shí)例」和「獲取所有服務(wù)的名稱」。
也就是說,對 getInstances()
方法進(jìn)行重寫肯定能實(shí)現(xiàn)本次目標(biāo)——跨命名空間訪問公共服務(wù)。
/**
?*?Return?all?instances?for?the?given?service.
?*?@param?serviceId?id?of?service
?*?@return?list?of?instances
?*?@throws?NacosException?nacosException
?*/
public?List<ServiceInstance>?getInstances(String?serviceId)?throws?NacosException?{
????????String?group?=?discoveryProperties.getGroup();
????????List<Instance>?instances?=?discoveryProperties.namingServiceInstance()
????????????????????????.selectInstances(serviceId,?group,?true);
????????return?hostToServiceInstanceList(instances,?serviceId);
}
/**
?*?Return?the?names?of?all?services.
?*?@return?list?of?service?names
?*?@throws?NacosException?nacosException
?*/
public?List<String>?getServices()?throws?NacosException?{
????????String?group?=?discoveryProperties.getGroup();
????????ListView<String>?services?=?discoveryProperties.namingServiceInstance()
????????????????????????.getServicesOfServer(1,?Integer.MAX_VALUE,?group);
????????return?services.getData();
}
復(fù)制代碼
03 最終解決思路及代碼示例
具體的解決方案思路大致如下:
-
生成一個(gè)共享配置類
NacosShareProperties
,用來配置共享公共服務(wù)的namespace
和group
; -
重寫配置類
NacosDiscoveryProperties
(新:NacosDiscoveryPropertiesV2
),將新增的共享配置類作為屬性放進(jìn)該配置類,后續(xù)會(huì)用到; -
重寫服務(wù)發(fā)現(xiàn)類
NacosServiceDiscovery
(新:NacosServiceDiscoveryV2
),這是最關(guān)鍵的邏輯; -
重寫自動(dòng)配置類
NacosDiscoveryAutoConfiguration
,將自定義相關(guān)類比 Nacos 原生類更早的注入容器。
最終代碼中用到了一些工具類,可以自行補(bǔ)充完整。
/**
?*?<pre>
?*??@description:?共享nacos屬性
?*??@author:?rookie0peng
?*??@date:?2022/8/29?15:22
?*??</pre>
?*/
@Configuration
@ConfigurationProperties(prefix?=?"nacos.share")
public?class?NacosShareProperties?{
????private?final?Map<String,?Set<String>>?NAMESPACE_TO_GROUP_NAME_MAP?=?new?ConcurrentHashMap<>();
????/**
?????*?共享nacos實(shí)體列表
?????*/
????private?List<NacosShareEntity>?entities;
????public?List<NacosShareEntity>?getEntities()?{
????????return?entities;
????}
????public?void?setEntities(List<NacosShareEntity>?entities)?{
????????this.entities?=?entities;
????}
????public?Map<String,?Set<String>>?getNamespaceGroupMap()?{
????????safeStream(entities).filter(entity?->?nonNull(entity)?&&?nonNull(entity.getNamespace()))
????????????????.forEach(entity?->?{
????????????????????Set<String>?groupNames?=?NAMESPACE_TO_GROUP_NAME_MAP.computeIfAbsent(entity.getNamespace(),?k?->?new?HashSet<>());
????????????????????if?(nonNull(entity.getGroupNames()))
????????????????????????groupNames.addAll(entity.getGroupNames());
????????????????});
????????return?new?HashMap<>(NAMESPACE_TO_GROUP_NAME_MAP);
????}
????@Override
????public?String?toString()?{
????????return?"NacosShareProperties{"?+
????????????????"entities="?+?entities?+
????????????????'}';
????}
????/**
?????*?共享nacos實(shí)體
?????*/
????public?static?final?class?NacosShareEntity?{
????????/**
?????????*?命名空間
?????????*/
????????private?String?namespace;
????????/**
?????????*?分組
?????????*/
????????private?List<String>?groupNames;
????????public?String?getNamespace()?{
????????????return?namespace;
????????}
????????public?void?setNamespace(String?namespace)?{
????????????this.namespace?=?namespace;
????????}
????????public?List<String>?getGroupNames()?{
????????????return?groupNames;
????????}
????????public?void?setGroupNames(List<String>?groupNames)?{
????????????this.groupNames?=?groupNames;
????????}
????????@Override
????????public?String?toString()?{
????????????return?"NacosShareEntity{"?+
????????????????????"namespace='"?+?namespace?+?'''?+
????????????????????",?groupNames="?+?groupNames?+
????????????????????'}';
????????}
????}
}
復(fù)制代碼
/**
?*?@description:?naocs服務(wù)發(fā)現(xiàn)屬性重寫
?*?@author:?rookie0peng
?*?@date:?2022/8/30?1:19
?*/
public?class?NacosDiscoveryPropertiesV2?extends?NacosDiscoveryProperties?{
????private?static?final?Logger?log?=?LoggerFactory.getLogger(NacosDiscoveryPropertiesV2.class);
????private?final?NacosShareProperties?nacosShareProperties;
????private?static?final?Map<String,?NamingService>?NAMESPACE_TO_NAMING_SERVICE_MAP?=?new?ConcurrentHashMap<>();
????public?NacosDiscoveryPropertiesV2(NacosShareProperties?nacosShareProperties)?{
????????super();
????????this.nacosShareProperties?=?nacosShareProperties;
????}
????public?Map<String,?NamingService>?shareNamingServiceInstances()?{
????????if?(!NAMESPACE_TO_NAMING_SERVICE_MAP.isEmpty())?{
????????????return?new?HashMap<>(NAMESPACE_TO_NAMING_SERVICE_MAP);
????????}
????????List<NacosShareProperties.NacosShareEntity>?entities?=?Optional.ofNullable(nacosShareProperties)
????????????????.map(NacosShareProperties::getEntities).orElse(Collections.emptyList());
????????entities.stream().filter(entity?->?nonNull(entity)?&&?nonNull(entity.getNamespace()))
????????????????.filter(PredicateUtil.distinctByKey(NacosShareProperties.NacosShareEntity::getNamespace))
????????????????.forEach(entity?->?{
????????????????????try?{
????????????????????????NamingService?namingService?=?NacosFactory.createNamingService(getNacosProperties(entity.getNamespace()));
????????????????????????if?(namingService?!=?null)?{
????????????????????????????NAMESPACE_TO_NAMING_SERVICE_MAP.put(entity.getNamespace(),?namingService);
????????????????????????}
????????????????????}?catch?(Exception?e)?{
????????????????????????log.error("create?naming?service?error!?properties={},?e=",?this,?e);
????????????????????}
????????????????});
????????return?new?HashMap<>(NAMESPACE_TO_NAMING_SERVICE_MAP);
????}
????private?Properties?getNacosProperties(String?namespace)?{
????????Properties?properties?=?new?Properties();
????????properties.put(SERVER_ADDR,?getServerAddr());
????????properties.put(USERNAME,?Objects.toString(getUsername(),?""));
????????properties.put(PASSWORD,?Objects.toString(getPassword(),?""));
????????properties.put(NAMESPACE,?namespace);
????????properties.put(UtilAndComs.NACOS_NAMING_LOG_NAME,?getLogName());
????????String?endpoint?=?getEndpoint();
????????if?(endpoint.contains(":"))?{
????????????int?index?=?endpoint.indexOf(":");
????????????properties.put(ENDPOINT,?endpoint.substring(0,?index));
????????????properties.put(ENDPOINT_PORT,?endpoint.substring(index?+?1));
????????}
????????else?{
????????????properties.put(ENDPOINT,?endpoint);
????????}
????????properties.put(ACCESS_KEY,?getAccessKey());
????????properties.put(SECRET_KEY,?getSecretKey());
????????properties.put(CLUSTER_NAME,?getClusterName());
????????properties.put(NAMING_LOAD_CACHE_AT_START,?getNamingLoadCacheAtStart());
//????????enrichNacosDiscoveryProperties(properties);
????????return?properties;
????}
}
復(fù)制代碼
/**
?*?@description:?naocs服務(wù)發(fā)現(xiàn)重寫
?*?@author:?rookie0peng
?*?@date:?2022/8/30?1:10
?*/
public?class?NacosServiceDiscoveryV2?extends?NacosServiceDiscovery?{
????private?final?NacosDiscoveryPropertiesV2?discoveryProperties;
????private?final?NacosShareProperties?nacosShareProperties;
????private?final?NacosServiceManager?nacosServiceManager;
????public?NacosServiceDiscoveryV2(NacosDiscoveryPropertiesV2?discoveryProperties,?NacosShareProperties?nacosShareProperties,?NacosServiceManager?nacosServiceManager)?{
????????super(discoveryProperties,?nacosServiceManager);
????????this.discoveryProperties?=?discoveryProperties;
????????this.nacosShareProperties?=?nacosShareProperties;
????????this.nacosServiceManager?=?nacosServiceManager;
????}
????/**
?????*?Return?all?instances?for?the?given?service.
?????*?@param?serviceId?id?of?service
?????*?@return?list?of?instances
?????*?@throws?NacosException?nacosException
?????*/
????public?List<ServiceInstance>?getInstances(String?serviceId)?throws?NacosException?{
????????String?group?=?discoveryProperties.getGroup();
????????List<Instance>?instances?=?discoveryProperties.namingServiceInstance()
????????????????.selectInstances(serviceId,?group,?true);
????????if?(isEmpty(instances))?{
????????????Map<String,?Set<String>>?namespaceGroupMap?=?nacosShareProperties.getNamespaceGroupMap();
????????????Map<String,?NamingService>?namespace2NamingServiceMap?=?discoveryProperties.shareNamingServiceInstances();
????????????for?(Map.Entry<String,?NamingService>?entry?:?namespace2NamingServiceMap.entrySet())?{
????????????????String?namespace;
????????????????NamingService?namingService;
????????????????if?(isNull(namespace?=?entry.getKey())?||?isNull(namingService?=?entry.getValue()))
????????????????????continue;
????????????????Set<String>?groupNames?=?namespaceGroupMap.get(namespace);
????????????????List<Instance>?shareInstances;
????????????????if?(isEmpty(groupNames))?{
????????????????????shareInstances?=?namingService.selectInstances(serviceId,?group,?true);
????????????????????if?(nonEmpty(shareInstances))
????????????????????????break;
????????????????}?else?{
????????????????????shareInstances?=?new?ArrayList<>();
????????????????????for?(String?groupName?:?groupNames)?{
????????????????????????List<Instance>?subShareInstances?=?namingService.selectInstances(serviceId,?groupName,?true);
????????????????????????if?(nonEmpty(subShareInstances))?{
????????????????????????????shareInstances.addAll(subShareInstances);
????????????????????????}
????????????????????}
????????????????}
????????????????if?(nonEmpty(shareInstances))?{
????????????????????instances?=?shareInstances;
????????????????????break;
????????????????}
????????????}
????????}
????????return?hostToServiceInstanceList(instances,?serviceId);
????}
????/**
?????*?Return?the?names?of?all?services.
?????*?@return?list?of?service?names
?????*?@throws?NacosException?nacosException
?????*/
????public?List<String>?getServices()?throws?NacosException?{
????????String?group?=?discoveryProperties.getGroup();
????????ListView<String>?services?=?discoveryProperties.namingServiceInstance()
????????????????.getServicesOfServer(1,?Integer.MAX_VALUE,?group);
????????return?services.getData();
????}
????public?static?List<ServiceInstance>?hostToServiceInstanceList(
????????????List<Instance>?instances,?String?serviceId)?{
????????List<ServiceInstance>?result?=?new?ArrayList<>(instances.size());
????????for?(Instance?instance?:?instances)?{
????????????ServiceInstance?serviceInstance?=?hostToServiceInstance(instance,?serviceId);
????????????if?(serviceInstance?!=?null)?{
????????????????result.add(serviceInstance);
????????????}
????????}
????????return?result;
????}
????public?static?ServiceInstance?hostToServiceInstance(Instance?instance,
????????????????????????????????????????????????????????String?serviceId)?{
????????if?(instance?==?null?||?!instance.isEnabled()?||?!instance.isHealthy())?{
????????????return?null;
????????}
????????NacosServiceInstance?nacosServiceInstance?=?new?NacosServiceInstance();
????????nacosServiceInstance.setHost(instance.getIp());
????????nacosServiceInstance.setPort(instance.getPort());
????????nacosServiceInstance.setServiceId(serviceId);
????????Map<String,?String>?metadata?=?new?HashMap<>();
????????metadata.put("nacos.instanceId",?instance.getInstanceId());
????????metadata.put("nacos.weight",?instance.getWeight()?+?"");
????????metadata.put("nacos.healthy",?instance.isHealthy()?+?"");
????????metadata.put("nacos.cluster",?instance.getClusterName()?+?"");
????????metadata.putAll(instance.getMetadata());
????????nacosServiceInstance.setMetadata(metadata);
????????if?(metadata.containsKey("secure"))?{
????????????boolean?secure?=?Boolean.parseBoolean(metadata.get("secure"));
????????????nacosServiceInstance.setSecure(secure);
????????}
????????return?nacosServiceInstance;
????}
????private?NamingService?namingService()?{
????????return?nacosServiceManager
????????????????.getNamingService(discoveryProperties.getNacosProperties());
????}
}
復(fù)制代碼
/**
?*?@description:?重寫nacos服務(wù)發(fā)現(xiàn)的自動(dòng)配置
?*?@author:?rookie0peng
?*?@date:?2022/8/30?1:08
?*/
@Configuration(proxyBeanMethods?=?false)
@ConditionalOnDiscoveryEnabled
@ConditionalOnNacosDiscoveryEnabled
@AutoConfigureBefore({NacosDiscoveryAutoConfiguration.class})
public?class?NacosDiscoveryAutoConfigurationV2?{
????@Bean
????@ConditionalOnMissingBean
????public?NacosDiscoveryPropertiesV2?nacosProperties(NacosShareProperties?nacosShareProperties)?{
????????return?new?NacosDiscoveryPropertiesV2(nacosShareProperties);
????}
????@Bean
????@ConditionalOnMissingBean
????public?NacosServiceDiscovery?nacosServiceDiscovery(
????????????NacosDiscoveryPropertiesV2?discoveryPropertiesV2,?NacosShareProperties?nacosShareProperties,?NacosServiceManager?nacosServiceManager
????)?{
????????return?new?NacosServiceDiscoveryV2(discoveryPropertiesV2,?nacosShareProperties,?nacosServiceManager);
????}
}
復(fù)制代碼
本以為問題到這就結(jié)束了,但最后自測時(shí)發(fā)現(xiàn)程序根本不走 Nacos
的服務(wù)發(fā)現(xiàn)邏輯,而是執(zhí)行 Ribbon
的負(fù)載均衡邏輯com.netflix.loadbalancer.AbstractLoadBalancerRule
。
不過實(shí)現(xiàn)類是 com.alibaba.cloud.nacos.ribbon.NacosRule
,繼續(xù)基于 NacosRule
重寫負(fù)載均衡。
/**
?*?@description:?共享nacos命名空間規(guī)則
?*?@author:?rookie0peng
?*?@date:?2022/8/31?2:04
?*/
public?class?ShareNacosNamespaceRule?extends?AbstractLoadBalancerRule?{
????private?static?final?Logger?LOGGER?=?LoggerFactory.getLogger(ShareNacosNamespaceRule.class);
????@Autowired
????private?NacosDiscoveryPropertiesV2?nacosDiscoveryPropertiesV2;
????@Autowired
????private?NacosShareProperties?nacosShareProperties;
????/**
?????*?重寫choose方法
?????*
?????*?@param?key
?????*?@return
?????*/
????@SneakyThrows
????@Override
????public?Server?choose(Object?key)?{
????????try?{
????????????String?clusterName?=?this.nacosDiscoveryPropertiesV2.getClusterName();
????????????DynamicServerListLoadBalancer?loadBalancer?=?(DynamicServerListLoadBalancer)?getLoadBalancer();
????????????String?name?=?loadBalancer.getName();
????????????NamingService?namingService?=?nacosDiscoveryPropertiesV2
????????????????????.namingServiceInstance();
????????????List<Instance>?instances?=?namingService.selectInstances(name,?true);
????????????if?(CollectionUtils.isEmpty(instances))?{
????????????????LOGGER.warn("no?instance?in?service?{},?then?to?get?share?service's?instance",?name);
????????????????List<Instance>?shareNamingService?=?this.getShareNamingService(name);
????????????????if?(nonEmpty(shareNamingService))
????????????????????instances?=?shareNamingService;
????????????????else
????????????????????return?null;
????????????}
????????????List<Instance>?instancesToChoose?=?instances;
????????????if?(org.apache.commons.lang3.StringUtils.isNotBlank(clusterName))?{
????????????????List<Instance>?sameClusterInstances?=?instances.stream()
????????????????????????.filter(instance?->?Objects.equals(clusterName,
????????????????????????????????instance.getClusterName()))
????????????????????????.collect(Collectors.toList());
????????????????if?(!CollectionUtils.isEmpty(sameClusterInstances))?{
????????????????????instancesToChoose?=?sameClusterInstances;
????????????????}
????????????????else?{
????????????????????LOGGER.warn(
????????????????????????????"A?cross-cluster?call?occurs,name?=?{},?clusterName?=?{},?instance?=?{}",
????????????????????????????name,?clusterName,?instances);
????????????????}
????????????}
????????????Instance?instance?=?ExtendBalancer.getHostByRandomWeight2(instancesToChoose);
????????????return?new?NacosServer(instance);
????????}
????????catch?(Exception?e)?{
????????????LOGGER.warn("NacosRule?error",?e);
????????????return?null;
????????}
????}
????@Override
????public?void?initWithNiwsConfig(IClientConfig?iClientConfig)?{
????}
????private?List<Instance>?getShareNamingService(String?serviceId)?throws?NacosException?{
????????List<Instance>?instances?=?Collections.emptyList();
????????Map<String,?Set<String>>?namespaceGroupMap?=?nacosShareProperties.getNamespaceGroupMap();
????????Map<String,?NamingService>?namespace2NamingServiceMap?=?nacosDiscoveryPropertiesV2.shareNamingServiceInstances();
????????for?(Map.Entry<String,?NamingService>?entry?:?namespace2NamingServiceMap.entrySet())?{
????????????String?namespace;
????????????NamingService?namingService;
????????????if?(isNull(namespace?=?entry.getKey())?||?isNull(namingService?=?entry.getValue()))
????????????????continue;
????????????Set<String>?groupNames?=?namespaceGroupMap.get(namespace);
????????????List<Instance>?shareInstances;
????????????if?(isEmpty(groupNames))?{
????????????????shareInstances?=?namingService.selectInstances(serviceId,?true);
????????????????if?(nonEmpty(shareInstances))
????????????????????break;
????????????}?else?{
????????????????shareInstances?=?new?ArrayList<>();
????????????????for?(String?groupName?:?groupNames)?{
????????????????????List<Instance>?subShareInstances?=?namingService.selectInstances(serviceId,?groupName,?true);
????????????????????if?(nonEmpty(subShareInstances))?{
????????????????????????shareInstances.addAll(subShareInstances);
????????????????????}
????????????????}
????????????}
????????????if?(nonEmpty(shareInstances))?{
????????????????instances?=?shareInstances;
????????????????break;
????????????}
????????}
????????return?instances;
????}
}
復(fù)制代碼
至此問題得以解決。
在 Nacos
上配置好共享 namespace
和 group
后,就能夠進(jìn)行跨命名空間訪問了。
# nacos共享命名空間配置 示例
nacos.share.entities[0].namespace=e6ed2017-3ed6-4d9b-824a-db626424fc7b
nacos.share.entities[0].groupNames[0]=DEFAULT_GROUP
# 指定服務(wù)使用共享的負(fù)載均衡規(guī)則,service-id是注冊到nacos上的服務(wù)id,ShareNacosNamespaceRule需要寫全限定名
service-id.ribbon.NFLoadBalancerRuleClassName=***.***.***.ShareNacosNamespaceRule
復(fù)制代碼
注意:如果 Java 項(xiàng)目的 nacos discovery
版本用的是 2021.1
,則不需要重寫 Ribbon 的負(fù)載均衡類,因?yàn)樵摪姹镜?Nacos 不依賴 Ribbon。
2.2.1.RELEASE 版本的 nacos discovery
依賴 Ribbon.
2021.1 版本的 nacos discovery
不依賴 Ribbon。
四、總結(jié)
為了達(dá)到共享命名空間的預(yù)期,構(gòu)思、查找資料、實(shí)現(xiàn)邏輯、調(diào)試,前后一共花費(fèi) 4 天左右。文章來源:http://www.zghlxwxcb.cn/news/detail-453463.html
但該功能仍然存在共享服務(wù)緩存等可優(yōu)化空間,留待后續(xù)實(shí)現(xiàn)。文章來源地址http://www.zghlxwxcb.cn/news/detail-453463.html
到了這里,關(guān)于重寫Nacos服務(wù)發(fā)現(xiàn):多個(gè)服務(wù)器如何跨命名空間,訪問公共服務(wù)?的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!