代码改变世界

Eureka获取IP地址逻辑

2019-08-04 22:39  深蓝大道  阅读(2388)  评论(0编辑  收藏  举报

在Eureka中如果不指定任何的Ip参数的话,那么提供者注册到Eureka中,消费者进行消费的时候访问的Ip为部署Eureka服务器的Ip地址。

 

 

那么正常情况下,服务器A调用将会调到服务B的身上,而此时如果在服务B中加入了一下的参数。那么就变了

eureka.instance.prefer-ip-address=true
eureka.instance.ip-address=172.12.9.0

此时服务C和服务B是相同的服务,部署在不同的服务器中,Ip地址不同,那么此时调用的服务将会被Eureka转发到服务C中。

 
 

 

源代码详解

我们可以在EurekaClientAutoConfiguration类中找到eurekaInstanceConfigBean方法。发现他在程序启动的时候就会加载一些eureka的配置信息

此时我们看到

String ipAddress = this.getProperty("eureka.instance.ip-address");
就是在这进行设置的,此时如果没有设置eureka.instance.ip-address参数的时候,那么此ipAddress是从EurekaInstanceConfigBean中初始化的。在配置bean中是通过网卡获取相关IP地址的。如果IP地址还是没获取到的话,再获取本机的IP地址。
EurekaInstanceConfigBean instance = new EurekaInstanceConfigBean(inetUtils);
public InetUtils.HostInfo findFirstNonLoopbackHostInfo() {
        InetAddress address = this.findFirstNonLoopbackAddress();
        if (address != null) {
            return this.convertAddress(address);
        } else {
            InetUtils.HostInfo hostInfo = new InetUtils.HostInfo();
            hostInfo.setHostname(this.properties.getDefaultHostname());
            hostInfo.setIpAddress(this.properties.getDefaultIpAddress());
            return hostInfo;
        }
    }

public InetAddress findFirstNonLoopbackAddress() {
InetAddress result = null;

try {
int lowest = 2147483647;
Enumeration nics = NetworkInterface.getNetworkInterfaces();

label61:
while(true) {
NetworkInterface ifc;
do {
while(true) {
do {
if (!nics.hasMoreElements()) {
break label61;
}

ifc = (NetworkInterface)nics.nextElement();
} while(!ifc.isUp());

this.log.trace("Testing interface: " + ifc.getDisplayName());
if (ifc.getIndex() >= lowest && result != null) {
if (result != null) {
continue;
}
break;
}

lowest = ifc.getIndex();
break;
}
} while(this.ignoreInterface(ifc.getDisplayName()));

Enumeration addrs = ifc.getInetAddresses();

while(addrs.hasMoreElements()) {
InetAddress address = (InetAddress)addrs.nextElement();
if (address instanceof Inet4Address && !address.isLoopbackAddress() && this.isPreferredAddress(address)) {
this.log.trace("Found non-loopback interface: " + ifc.getDisplayName());
result = address;
}
}
}
} catch (IOException var8) {
this.log.error("Cannot get first non-loopback address", var8);
}

if (result != null) {
return result;
} else {
try {
return InetAddress.getLocalHost();
} catch (UnknownHostException var7) {
this.log.warn("Unable to retrieve localhost");
return null;
}
}
}
 

 

 通过源码可以看出,该工具类会获取所有网卡,依次进行遍历,取ip地址合理、索引值最小且不在忽略列表的网卡的ip地址作为结果。如果仍然没有找到合适的IP, 那么就将InetAddress.getLocalHost()做为最后的fallback方案。
 
 如果以上方法都无法获取IP地址的话,那就使用默认的:127.0.0.1
 
 
手动忽略网卡设置:
spring.cloud.inetutils.ignored-interfaces=eth0