zoukankan      html  css  js  c++  java
  • Eureka服务注册过程详解之IpAddress(详解eureka.instance.prefer-ip-address = true 与 eureka.instance.prefer-ip-address)

    分析,eureka.instance.prefer-ip-address

    • 本节解释为什么配置eureka.instance.prefer-ip-address = true时,注册到Eureka Server上的是IP,以及是什么IP

    老套路,定位问题从配置开始。

    (1) 我们通过eureka.instance.prefer-ip-address 配置项,可以找到源码

    org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean.preferIpAddress

    (2) preferIpAddress被哪里调用,可以找到

    org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean.getHostName(boolean)

    代码如下:

    @Override
    public String getHostName(boolean refresh) {
        if (refresh && !this.hostInfo.override) {
            this.ipAddress = this.hostInfo.getIpAddress();
            this.hostname = this.hostInfo.getHostname();
        }
        return this.preferIpAddress ? this.ipAddress : this.hostname;
    }

    我们看到以上代码有个hostInfo,这是在哪里实例化的呢?从这里我们可以知道,为什么配置eureka.instance.prefer-ip-address = true 就可以将IP注册到Eureka Server上,而如果不配置就是机器的主机名。

    (3) hostInfo在

    org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean

    的构造方法中实例化!我们来阅读该类的构造方法:

    public EurekaInstanceConfigBean(InetUtils inetUtils) {
        this.inetUtils = inetUtils;
        this.hostInfo = this.inetUtils.findFirstNonLoopbackHostInfo();
        this.ipAddress = this.hostInfo.getIpAddress();
        this.hostname = this.hostInfo.getHostname();
    }

    从中可以看到,hostInfo是调用了

    this.inetUtils.findFirstNonLoopbackHostInfo();

    从中可以看到,原来hostInfo是调用了

    org.springframework.cloud.commons.util.InetUtils.findFirstNonLoopbackHostInfo()


    (4)阅读

    可以看到以下代码:

    public HostInfo findFirstNonLoopbackHostInfo() {
        InetAddress address = findFirstNonLoopbackAddress();
        if (address != null) {
            return convertAddress(address);
        }
        HostInfo hostInfo = new HostInfo();
        hostInfo.setHostname(this.properties.getDefaultHostname());
        hostInfo.setIpAddress(this.properties.getDefaultIpAddress());
        return hostInfo;
    }

    我们再看一下该类的

    org.springframework.cloud.commons.util.InetUtils.findFirstNonLoopbackAddress()

    方法:

    public InetAddress findFirstNonLoopbackAddress() {
        InetAddress result = null;
        try {
            int lowest = Integer.MAX_VALUE;
            for (Enumeration<NetworkInterface> nics = NetworkInterface
                    .getNetworkInterfaces(); nics.hasMoreElements();) {
                NetworkInterface ifc = nics.nextElement();
                if (ifc.isUp()) {
                    log.trace("Testing interface: " + ifc.getDisplayName());
                    if (ifc.getIndex() < lowest || result == null) {
                        lowest = ifc.getIndex();
                    }
                    else if (result != null) {
                        continue;
                    }
                    // @formatter:off
                    if (!ignoreInterface(ifc.getDisplayName())) {
                        for (Enumeration<InetAddress> addrs = ifc
                                .getInetAddresses(); addrs.hasMoreElements();) {
                            InetAddress address = addrs.nextElement();
                            if (address instanceof Inet4Address
                                    && !address.isLoopbackAddress()
                                    && !ignoreAddress(address)) {
                                log.trace("Found non-loopback interface: "
                                        + ifc.getDisplayName());
                                result = address;
                            }
                        }
                    }
                    // @formatter:on
                }
            }
        }
        catch (IOException ex) {
            log.error("Cannot get first non-loopback address", ex);
        }
        if (result != null) {
            return result;
        }
        try {
            return InetAddress.getLocalHost();
        }
        catch (UnknownHostException e) {
            log.warn("Unable to retrieve localhost");
        }
        return null;
    }

    eureka.instance.ip-address和eureka.instance.prefer-ip-address = true同时设置,会用自动获取的ip还是手动设置的?至此,终于找到了获得IP的详细方法,原来只需要配置eureka.instance.prefer-ip-address = true,Spring就会自动为我们获取第一个非回环IP地址(这只是简单的说法,事实上这段代码有些容错的处理)。代码虽然长,但是很清晰。不做赘述。

    上文是讨论设置eureka.instance.prefer-ip-address = true ,但没有指定eureka.instance.ip-address 的情况。那么如果两者都被指定了,Spring会怎么处理呢?是使用eureka.instance.ip-address手动设置的IP,还是用上面自动获取的IP呢?

    答案是听eureka.instance.ip-address的。

    原因是:在

    org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean.setIpAddress(String)

    中:

    publicvoid setIpAddress(String ipAddress) {
      this
    .ipAddress = ipAddress;   this.hostInfo.override = true; }

    这边设置了this.hostInfo.override,因此会导致getHostName方法不会进if语句,直接返回this.ipAddress。 

    @Override
    public String getHostName(boolean refresh) {
        if (refresh && !this.hostInfo.override) {
            this.ipAddress = this.hostInfo.getIpAddress();
            this.hostname = this.hostInfo.getHostname();
        }
        return this.preferIpAddress ? this.ipAddress : this.hostname;
    }

    回到上文的B.T.W

    org.springframework.cloud.commons.util.InetUtils.findFirstNonLoopbackAddress()

    答案非常简单,详见Spring Cloud官方文档:方法,上面有很多ignoreXXX的代码。那么,如何配置想要忽略的网卡或者IP地址呢?

    http://cloud.spring.io/spring-cloud-static/Camden.SR3/#ignore-network-interfaces

    当然了,这些配置的本意并不是用来注册到Eureka上的,而是用作其他用途,只不过如果没有设置eureka.instance.ip-address时,这个IP就是注册到Eureka Server上的IP。

    我们可以在应用的/env端点看到Spring为我们挑选的IP:

    springCloudClientHostInfo: {
    spring.cloud.client.hostname: "itmuch",
    spring.cloud.client.ipAddress: "192.168.0.59"
    },
  • 相关阅读:
    XJOI网上同步训练DAY2 T2
    XJOI网上同步训练DAY2 T1
    BZOJ 2661 连连看
    HDU 4411 Arrest
    BZOJ 2324 营救皮卡丘
    BZOJ 1927 星际竞速
    BZOJ 3550 Vacation
    XJOI网上同步训练DAY1 T3
    php 类的相互访问
    ThinkPhp5.0_文件上传
  • 原文地址:https://www.cnblogs.com/liaojie970/p/8794120.html
Copyright © 2011-2022 走看看