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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM