[转帖]重写Nacos服务发现逻辑动态修改远程服务IP地址

重写,nacos,服务,发现,逻辑,动态,修改,远程,ip地址 · 浏览次数 : 0

小编点评

## Nacos Discovery Client配置问题分析 此文章描述了 Nacos Discovery Client 配置中出现无法访问其他微服务的问题,并分析了问题原因。 **问题背景:** * 开发环境上使用了 K8S,所有微服务注册在 K8S 内虚拟 IP。 * 本机开发联调调用其他微服务,但无法访问。 **解决方案:** 1. 使用 **KT Connect** 工具进行 VPN 连接,可以解决跨集群网络连接问题。 2. 配置 **Ribbon** 的 `listOfServers` 属性,并将 IP 地址格式化为 ``. 3. 重写 `NacosNamingService` 的 `namingServiceInstance` 方法,手动设置远程服务注册 IP。 4. 在 `DevEnvironmentNacosDiscoveryProperties` 中设置远程服务注册 IP。 5. 使用 `DevEnvironmentNacosNamingService` 来实现跨集群服务 Discovery。 **问题分析:** * **KT Connect** 解决方案需要设置 VPN tunnel,可能会影响性能和安全性。 * **Ribbon** 配置方法简单易懂,但需要维护配置文件,并可能存在配置错误的问题。 * **手动设置 IP地址** 允许开发者更加精确地控制服务注册地址,但需要编写代码。 * **NacosNamingService` 的 `selectInstances` 方法默认从 `serverAddr` 属性中获取 IP地址,如果服务地址格式不正确,无法访问远程服务。 * **`DevEnvironmentNacosDiscoveryProperties` 中设置远程服务注册 IP,可以解决服务地址格式问题,但需要特殊处理 IP 地址格式的 service 的注册。 **总结:** 在 Nacos Discovery Client 配置中,设置远程服务注册 IP 需要考虑服务地址格式、 VPN 连接、配置复杂性和代码维护性。建议使用 **KT Connect** 工具进行 VPN 连接,并根据实际情况调整 **Ribbon** 或自定义 `NacosNamingService` 的配置方式。

正文

https://www.cnblogs.com/changxy-codest/p/14632574.html

 

背景

还是先说下做这个的背景,开发环境上了K8S,所有的微服务都注册在K8S内的Nacos,注册地址为K8S内部虚拟IP,K8S内的服务之间相互调用没有问题,但是本机开发联调调用其他微服务就访问不到。

 

解决方案

1、KT Connect,可以理解为一个VPN工具,可以和K8S网络联通,缺点是配置繁琐,每次开发都需要启动KT Connect程序;

2、配置Ribbon的listOfServers,配置如下:

<nacosServiceName>.ribbon.listOfServers=<ip:port>

3、Nacos Client从Nacos Server获取服务列表时,修改远程服务对应的IP地址。

 

重写NacosNamingService

1、看了下nacos-client源码,发现有个NacosNamingService类,主要是服务发现的实现类,可以从这里入手修改远程服务注册IP;

2、NacosNamingService是在NacosDiscoveryClientAutoConfiguration通过注入NacosDiscoveryProperties初始化的,具体源码如下:

@Bean
@ConditionalOnMissingBean
public NacosDiscoveryProperties nacosProperties() {
    return new NacosDiscoveryProperties();
}

3、跟踪到NacosDiscoveryProperties,初始化NacosNamingService的核心代码如下:

复制代码
    public NamingService namingServiceInstance() {
        if (null != this.namingService) {
            return this.namingService;
        } else {
            Properties properties = new Properties();
            properties.put("serverAddr", this.serverAddr);
            properties.put("namespace", this.namespace);
            properties.put("com.alibaba.nacos.naming.log.filename", this.logName);
            if (this.endpoint.contains(":")) {
                int index = this.endpoint.indexOf(":");
                properties.put("endpoint", this.endpoint.substring(0, index));
                properties.put("endpointPort", this.endpoint.substring(index + 1));
            } else {
                properties.put("endpoint", this.endpoint);
            }

            properties.put("accessKey", this.accessKey);
            properties.put("secretKey", this.secretKey);
            properties.put("clusterName", this.clusterName);
            properties.put("namingLoadCacheAtStart", this.namingLoadCacheAtStart);

            try {
                this.namingService = NacosFactory.createNamingService(properties);
            } catch (Exception var3) {
                log.error("create naming service error!properties={},e=,", this, var3);
                return null;
            }

            return this.namingService;
        }
    }
复制代码

4、我们直接重新namingServiceInstance方法就可以了,具体实现代码如下:

复制代码
@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;
        }
    }

}

与[转帖]重写Nacos服务发现逻辑动态修改远程服务IP地址相似的内容: