Nacos: 注册服务获取IP的问题

Created on 19 Nov 2018  ·  22Comments  ·  Source: alibaba/nacos

我用docker swarm来部署的nacos和服务。
服务容器启动后,会有两个IP地址,一个是内置的ingress网络的地址(10.255.12.245),另外一个是我自定义的网络的地址(10.0.0.27)。
在nacos服务列表里看到,注册的服务用的IP地址都是ingress网络的IP地址,而没有用我自定义的网络的IP地址。而在sentinel和spring cloud admin中,识别出来的IP地址,都是自定义的网络地址。
我不知道这是随机出现的巧合,还是sentinel和spring cloud admin对此有特殊的处理,我尝试启动多个容器,发现结果都是这样的,nacos总是用ingress网络的IP地址,而sentinel和spring cloud admin总是用自定义网络的地址。

Most helpful comment

@SoyMeng 我也出现了在linux下不同主机下docker部署的问题,我的环境是docker容器,网络使用的桥接,选网卡可以找到eth0,但是这个eth0下的ip是容器的内网ip,固定ip这方式只能让保证每个服务开一个实例,这并不太现实,所以请教您有什么其它的办法么?

All 22 comments

补充下,还出现了同一个容器中的ingress网络IP地址和自定义网络IP地址被识别为两个实例的情况。

@Jnoee 你用的什么客户端注册的服务,注册的IP是由客户端传入的,并非Nacos自己获取的

补充下,还出现了同一个容器中的ingress网络IP地址和自定义网络IP地址被识别为两个实例的情况。

不同的IP就会被视为不同的实例。

我也遇到这个问题了 nacos总是识别到docker的ip nacos能再垃圾点吗

nacos-server是作为服务发现的中心,当nacos-client注册到nacos-server,之后client之间如何通讯是根据client配置的实例ip及port决定的。ip是否可达是根据client之间的网络拓扑决定的。所以设计为client自己配置ip!

怎样解决你的问题,其实看源码之后就很简单了

以spring-cloud为例

这是spring-cloud中client配置获取自身ip的一段代码
org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties

@PostConstruct
    public void init() throws SocketException {

        serverAddr = Objects.toString(serverAddr, "");
        endpoint = Objects.toString(endpoint, "");
        namespace = Objects.toString(namespace, "");
        logName = Objects.toString(logName, "");

        if (StringUtils.isEmpty(ip)) {
            // traversing network interfaces if didn't specify a interface
            if (StringUtils.isEmpty(networkInterface)) {
                ip = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
            }
            else {
                NetworkInterface netInterface = NetworkInterface
                        .getByName(networkInterface);
                if (null == networkInterface) {
                    throw new IllegalArgumentException(
                            "no such interface " + networkInterface);
                }

                Enumeration<InetAddress> inetAddress = netInterface.getInetAddresses();
                while (inetAddress.hasMoreElements()) {
                    InetAddress currentAddress = inetAddress.nextElement();
                    if (currentAddress instanceof Inet4Address
                            && !currentAddress.isLoopbackAddress()) {
                        ip = currentAddress.getHostAddress();
                        break;
                    }
                }

                if (StringUtils.isEmpty(ip)) {
                    throw new RuntimeException("cannot find available ip from"
                            + " network interface " + networkInterface);
                }

            }
        }

        this.overrideFromEnv(environment);
    }

这是自动注册到nacos-server的代码
org.springframework.cloud.alibaba.nacos.NacosDiscoveryClientAutoConfiguration

/*
 * Copyright (C) 2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.cloud.alibaba.nacos;

import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author xiaojing
 */
@Configuration
@ConditionalOnMissingBean(DiscoveryClient.class)
@ConditionalOnNacosDiscoveryEnabled
@EnableConfigurationProperties
public class NacosDiscoveryClientAutoConfiguration {

    @Bean
    public DiscoveryClient nacosDiscoveryClient() {
        return new NacosDiscoveryClient();
    }

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

}

要想实现你的功能你需要修改client端注册代码,重写NacosDiscoveryClientAutoConfiguration 并 设置NacosDiscoveryProperties中的信息,例如ip,网卡等

同遇到这个问题,直接Close是什么意思?

同遇到这个问题,直接Close是什么意思?

为什么close:

  1. 这是一个spring-cloud-alibaba客户端的问题,请到spring-cloud-alibaba提问;
  2. 这也不是一个需要修复的bug,如果你看了spring-cloud-alibaba文档,就知道可以通过指定网卡来选择注册的IP;

同遇到这个问题,直接Close是什么意思?

为什么close:

  1. 这是一个spring-cloud-alibaba客户端的问题,请到spring-cloud-alibaba提问;
  2. 这也不是一个需要修复的bug,如果你看了spring-cloud-alibaba文档,就知道可以通过指定网卡来选择注册的IP;

您的解释我认可,但issues的存在就是提供问题的路径(这个issues描述的场景还是挺具体的),我觉得上面的回答太过粗暴了,至少您上面的回复可以给后来者提供一个去spring-cloud-alibaba寻求的帮助的依据。

同遇到这个问题,直接Close是什么意思?

为什么close:

  1. 这是一个spring-cloud-alibaba客户端的问题,请到spring-cloud-alibaba提问;
  2. 这也不是一个需要修复的bug,如果你看了spring-cloud-alibaba文档,就知道可以通过指定网卡来选择注册的IP;

您的解释我认可,但issues的存在就是提供问题的路径(这个issues描述的场景还是挺具体的),我觉得上面的回答太过粗暴了,至少您上面的回复可以给后来者提供一个去spring-cloud-alibaba寻求的帮助的依据。

赞同,既然都是阿里巴巴出品的,而且选为Spring cloud alibaba的注册中心了,问题就不要这样抛来抛去,作为注册中心,不就是要来管理注册来的服务的,这样抛给客户端合适吗,而且nacos中关于多网卡选择那边也描述不清,是不是会影响注册服务的IP选择也不说清楚。

同遇到这个问题,直接Close是什么意思?

为什么close:

  1. 这是一个spring-cloud-alibaba客户端的问题,请到spring-cloud-alibaba提问;
  2. 这也不是一个需要修复的bug,如果你看了spring-cloud-alibaba文档,就知道可以通过指定网卡来选择注册的IP;

您的解释我认可,但issues的存在就是提供问题的路径(这个issues描述的场景还是挺具体的),我觉得上面的回答太过粗暴了,至少您上面的回复可以给后来者提供一个去spring-cloud-alibaba寻求的帮助的依据。

之前回复是有点草率,后续会改进,欢迎监督。

同遇到这个问题,直接Close是什么意思?

为什么close:

  1. 这是一个spring-cloud-alibaba客户端的问题,请到spring-cloud-alibaba提问;
  2. 这也不是一个需要修复的bug,如果你看了spring-cloud-alibaba文档,就知道可以通过指定网卡来选择注册的IP;

您的解释我认可,但issues的存在就是提供问题的路径(这个issues描述的场景还是挺具体的),我觉得上面的回答太过粗暴了,至少您上面的回复可以给后来者提供一个去spring-cloud-alibaba寻求的帮助的依据。

赞同,既然都是阿里巴巴出品的,而且选为Spring cloud alibaba的注册中心了,问题就不要这样抛来抛去,作为注册中心,不就是要来管理注册来的服务的,这样抛给客户端合适吗,而且nacos中关于多网卡选择那边也描述不清,是不是会影响注册服务的IP选择也不说清楚。

感谢你的建议,nacos和Spring cloud alibaba都是阿里巴巴出品的,但是也是以开源软件的形式运作的,所以请到对应的仓库提出相应的问题。

@Jnoee 同样遇到一样的问题,请问题主解决了吗?能不能分享下是怎么解决的

@Sxxjava
这个问题确实应该属于Spring cloud alibaba的问题,参考org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties的配置

如果选择固定Ip注册可以配置

spring.cloud.nacos.discovery.ip = xx
spring.cloud.nacos.discovery.port = xxx

如果选择固定网卡配置项

spring.cloud.nacos.discovery.networkInterface = xx

如果想更丰富的选择,可以使用spring cloud 的 InetUtils工具,配置项为,具体说明可以自行检索

spring.cloud.inetutils.default-hostname
spring.cloud.inetutils.default-ip-address
spring.cloud.inetutils.ignored-interfaces
spring.cloud.inetutils.preferred-networks
spring.cloud.inetutils.timeout-seconds
spring.cloud.inetutils.use-only-site-local-interfaces

@SoyMeng 谢谢,解决了

@SoyMeng 客户端获取内网ip 这个问题有解决吗?现在出现同样的问题。在linux不同服务器下部署不同服务。服务间调用不可用。

@singledemon 这个issues说的是在docker部署下的问题,大部分情况配置网卡名称就可以了,您需要自己判断是什么原因产生的。参看我上面的回答

@SoyMeng 我也出现了在linux下不同主机下docker部署的问题,我的环境是docker容器,网络使用的桥接,选网卡可以找到eth0,但是这个eth0下的ip是容器的内网ip,固定ip这方式只能让保证每个服务开一个实例,这并不太现实,所以请教您有什么其它的办法么?

@hellxz 同样遇到这个问题,解决了吗

@hellxz 同样遇到这个问题,解决了吗

我最后用的 @SoyMeng 的办法

spring.cloud.nacos.discovery.ip = xx
spring.cloud.nacos.discovery.port = xxx

加到启动容器命令里,向容器内的java程序传递ip和端口号
-Dspring.cloud.nacos.discovery.ip=xx -Dspring.cloud.nacos.discovery.port=xxx

代码中依赖com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-discovery:2.1.1.RELEASE
其中nacos客户端版本是com.alibaba.nacos:nacos-client:1.1.4
nacos server使用github上1.1.4版本的tar.gz,三台本地虚拟机组成的集群,连接本地mysql,启动无异常。
nacos控制台可以正常打开和使用。

问题:注册服务时,提示连接超时,下面是日志:

java.lang.IllegalStateException: failed to req API:/nacos/v1/ns/instance after all servers([192.168.20.21:8848]) tried: failed to req API:192.168.20.21:8848/nacos/v1/ns/instance. code:500 msg: java.net.SocketTimeoutException: Read timed out
at com.alibaba.nacos.client.naming.net.NamingProxy.reqAPI(NamingProxy.java:467) ~[nacos-client-1.1.4.jar:na]
    at com.alibaba.nacos.client.naming.net.NamingProxy.reqAPI(NamingProxy.java:389) ~[nacos-client-1.1.4.jar:na]
    at com.alibaba.nacos.client.naming.net.NamingProxy.registerService(NamingProxy.java:191) ~[nacos-client-1.1.4.jar:na]
    at com.alibaba.nacos.client.naming.NacosNamingService.registerInstance(NacosNamingService.java:207) ~[nacos-client-1.1.4.jar:na]
    at com.alibaba.cloud.nacos.registry.NacosServiceRegistry.register(NacosServiceRegistry.java:63) ~[spring-cloud-alibaba-nacos-discovery-2.1.1.RELEASE.jar:2.1.1.RELEASE]
    at org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration.register(AbstractAutoServiceRegistration.java:239) [spring-cloud-commons-2.2.0.RC1.jar:2.2.0.RC1]
    at com.alibaba.cloud.nacos.registry.NacosAutoServiceRegistration.register(NacosAutoServiceRegistration.java:75) [spring-cloud-alibaba-nacos-discovery-2.1.1.RELEASE.jar:2.1.1.RELEASE]
    at org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration.start(AbstractAutoServiceRegistration.java:138) [spring-cloud-commons-2.2.0.RC1.jar:2.2.0.RC1]

能帮忙看下这个是什么问题吗?

@CharleyCao 同样遇到这个问题,解决了吗?

@zhiyuan5 解决了。需要配置Linux本地的hosts和hostname

Was this page helpful?
0 / 5 - 0 ratings