[SpringCloud-Eureka] zookeeper和Eureka使用IP注册
在使用Eureka和Zookeeper作为注册中心的时候,均是默认注册主机名称,但是很多时候主机名称解析会有问题,通过配置使用IP注册:Eureka:eureka.instance.prefer-ip-address = trueZookeeperzookeeper中的配置很隐蔽,查了很久,配置形式如下:spring.cloud.zookeeper.dis...
·
一.注册IP而不是服务名称
1.1 问题 : 在使用Eureka和Zookeeper作为注册中心的时候,均是默认注册主机名称,但是很多时候主机名称解析会有问题,通过配置使用IP注册:
Eureka:
eureka.instance.prefer-ip-address = true
Zookeeper:
zookeeper中的配置很隐蔽,查了很久,配置形式如下:
spring.cloud.zookeeper.discovery.instance-host=${spring.cloud.client.ipAddress}
这里右边可以写成IP,但是写成IP不好,比如使用配置中心多实例共享一份配置就有问题,因此写成这样,会
动态获取实例运行的主机的ip。配置后,就可以将IP注册到zookeeper,其他服务使用Feign调用就不会有问题了。
二.Eureka注册IP解读
2.1 配置注册IP
通过eureka.instance.prefer-ip-address = true配置,将微服务的IP注册到Eureka,而不是主机名称
代码解析如下:
在org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean类的getHostName方法中:
@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;
}
这里可以看到最后返回时通过preferIpAddress配置项来决定返回的是IP还是主机名称,如下所示,默认是false,
也就是默认注册的是this.hostname主机名称:
/**
* Flag to say that, when guessing a hostname, the IP address of the server should be
* used in prference to the hostname reported by the OS.
*/
private boolean preferIpAddress = false;
- 总言之:eureka.instance.prefer-ip-address = true通过该配置项可以往Eureka注册IP而不是主机名(默认是主机名称);
2.2 配置自定义IP
配置项spring.cloud.client.ipAddress可指定一个IP,如果指定了IP同时开启eureka.instance.prefer-ip-address=true
的话,那么会注册哪一个信息呢?我们跟进if (refresh && !this.hostInfo.override) 这个判断条件,refresh如果为false则
直接走下面的return返回不会再去执行两个get方法(可以理解为不去重新获取,即不refresh刷新),那么条件取决于
HostInfo的override属性,跟进:根据setIpAddress方法我们看到,当设置了eureka.instance.ipAddress时,override
会设置为true,,那么在执行上面的逻辑的时候,就不会再执行hostInfo的getIpAddress和getHostname方法了,因此
就会直接返回this.ipAddress,而这个ipAddress就是spring.cloud.client.ipAddress指定的。
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
this.hostInfo.override = true;
}
- 总言之:配置了eureka.instance.prefer-ip-address = true和spring.cloud.client.ipAddress的情况下,会注册spring.cloud.client.ipAddress指定的IP,而不会通过findFirstNonLoopbackHostInfo方法去寻找本机的非回环地址;
3.findFirstNonLoopbackAddress方法
下面是简单改造过的findFirstNonLoopbackAddress方法,通过该方法可以获取本机的非回环IP地址
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
for (Enumeration<InetAddress> addrs = ifc
.getInetAddresses(); addrs.hasMoreElements();) {
InetAddress address = addrs.nextElement();
if (address instanceof Inet4Address
&& !address.isLoopbackAddress()
) {
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;
}
更多推荐
已为社区贡献4条内容
所有评论(0)