Eureka服务注册过程详解之IpAddress
Posted yunyunde
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Eureka服务注册过程详解之IpAddress相关的知识,希望对你有一定的参考价值。
转自:http://www.itmuch.com/spring-cloud-code-read/spring-cloud-code-read-eureka-registry-ip/
系列文章都写得特别好,转过来给自己参考。
先说一下结论,
如果eureka.instance.prefer-ip-address = true 则Spring就会为我们自动获取IP;
如果eureka.instance.ip-address 与 eureka.instance.prefer-ip-address = true 同时设置,则使用eureka.instance.ip-address 设置的ip;
这些配置的本意并不是用来注册到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" ,
本文内容:
- 微服务注册到Eureka Server上的粗粒度过程
eureka.instance.prefer-ip-address = true
时,发生的一些事- 深度理解
eureka.instance.ip-address
和eureka.instance.prefer-ip-address = true
。
为什么配置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;
从这里我们可以知道,为什么配置eureka.instance.prefer-ip-address = true
就可以将IP注册到Eureka Server上,而如果不配置就是机器的主机名。
我们看到以上代码有个hostInfo,这是在哪里实例化的呢?
(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) 阅读
org.springframework.cloud.commons.util.InetUtils.findFirstNonLoopbackHostInfo()
可以看到以下代码:
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;
至此,终于找到了获得IP的详细方法,原来只需要配置eureka.instance.prefer-ip-address = true,Spring就会自动为我们获取第一个非回环IP地址(这只是简单的说法,事实上这段代码有些容错的处理)。
eureka.instance.ip-address和eureka.instance.prefer-ip-address = true同时设置,会用自动获取的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)
中:
public void 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;
以上是关于Eureka服务注册过程详解之IpAddress的主要内容,如果未能解决你的问题,请参考以下文章