一、问题背景
在开发某个公共应用时,笔者发现该公共应用的数据是所有测试环境(假设存在 dev/dev2/dev3)通用的。
这就意味着只需部署一个应用,就能满足所有测试环境的需求;也意味着所有测试环境都需要调用该公共应用,而不同测试环境的应用注册在不同的 Nacos 命名空间。
二、两种解决方案
如果所有测试环境都需要调用该公共应用,有两种可行的方案。第一种,将该公共服务同时注册到不同的测试环境所对应的命名空间中。
第二种,将公共应用注册到单独的命名空间,不同的测试环境能够跨命名空间访问该应用。
三、详细的问题解决过程
先行交代笔者的版本号配置。Nacos 客户端版本号为 NACOS 1.4.1
;Java 项目的 Nacos 版本号如下。
最初想法是将该公共应用同时注册到多个命名空间下。
01 注册多个命名空间
从该博客中,我们看到其他程序员朋友也遇到了类似的公共服务的需求。在本篇文章中,笔者将进一步分享实现思路以及示例代码。
说明:以下代码内容来自用户 chuntaojun 的分享。
shareNamespace={namespaceId[:group]},{namespaceId[:group]}
复制代码
@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())));
}
}
复制代码
进一步考虑后发现该解决方案可能不太契合当前遇到的问题。公司目前的开发测试环境有很多个,并且不确定以后会不会继续增加。
如果每增加一个环境,都需要修改一次公共服务的配置,并且重启一次公共服务,着实太麻烦了。倒不如反其道而行,让其他的服务器实现跨命名空间访问公共服务。
02 跨命名空间访问
针对实际问题查找资料时,我们找到了类似的参考分享《重写 Nacos 服务发现逻辑动态修改远程服务IP地址》。
跟着博客思路看代码,笔者了解到服务发现的主要相关类是 NacosNamingService
, NacosDiscoveryProperties
, NacosDiscoveryAutoConfiguration
。
然后,笔者将博客的示例代码复制过来,试着进行如下调试:
@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 namingSer