zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    WDA学习(14):Colors Cell and Input Enable to ALV Column
    JavaScript try-catch语句(错误处理)
    constructor
    input file 重复上传同一张图片失效的解决办法
    input下拉带输入框
    box-shaw四边阴影详解
    苹方字体合集
    两个div不同高度并排显示
    弹窗库
    webstorm破解安装版本
  • 原文地址:https://www.cnblogs.com/yunyunde/p/11205694.html
Copyright © 2011-2022 走看看