多个ip到底用哪个?
上次说到instanceinfo的hostname,ip,那么这些值是从哪来的呢?
public EurekaInstanceConfigBean(InetUtils inetUtils) {
this.inetUtils = inetUtils;
this.hostInfo = this.inetUtils.findFirstNonLoopbackHostInfo();
this.ipAddress = this.hostInfo.getIpAddress();
this.hostname = this.hostInfo.getHostname();
}
可以看到是从InetUtils类获取的,而这个类是从InetUtilsProperties获取数据
及从配置文件spring.cloud.inetutils
开头的配置获取。
你可以设置忽略的网卡,或者优先选择的网卡,这两个设置都支持正则
// @formatter:off
if (!ignoreInterface(ifc.getDisplayName())) {
for (Enumeration<InetAddress> addrs = ifc
.getInetAddresses(); addrs.hasMoreElements();) {
InetAddress address = addrs.nextElement();
if (address instanceof Inet4Address
&& !address.isLoopbackAddress()
&& isPreferredAddress(address)) {
log.trace("Found non-loopback interface: "
+ ifc.getDisplayName());
result = address;
}
}
}
// @formatter:on
如果这两个设置你都不满意,你可以设置忽略值为.*
,忽略所有网卡
然后用hostname从/etc/hosts中获取ip,也就是说你要在/etc/hosts设置你的ip对应的本机hostname
如果你认为这样就完事了,那就是大错特错。
通过查找InetUtils.findFirstNonLoopbackAddress引用发现,在HostInfoEnvironmentPostProcessor类中,并未使用配置文件的参数,而是直接创建了一个对象。
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) {
InetUtils.HostInfo hostInfo = getFirstNonLoopbackHostInfo(environment);
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
map.put("spring.cloud.client.hostname", hostInfo.getHostname());
map.put("spring.cloud.client.ip-address", hostInfo.getIpAddress());
MapPropertySource propertySource = new MapPropertySource(
"springCloudClientHostInfo", map);
environment.getPropertySources().addLast(propertySource);
}
private HostInfo getFirstNonLoopbackHostInfo(ConfigurableEnvironment environment) {
InetUtilsProperties target = new InetUtilsProperties();
ConfigurationPropertySources.attach(environment);
Binder.get(environment).bind(InetUtilsProperties.PREFIX,
Bindable.ofInstance(target));
try (InetUtils utils = new InetUtils(target)) {
return utils.findFirstNonLoopbackHostInfo();
}
}
虽然是new了一个对象,但是其实使用了environment设置了属性,那么我们有两种方案。
- 在启动参数中传入参数,比如--spring.cloud.inetutils.ignoredInterfaces=.*
- 创建一个EnvironmentPostProcessor类,并且该类的order要比HostInfoEnvironmentPostProcessor小,及优先加载我们定义的
public class InspectEurekaClientIp implements BeanPostProcessor, EnvironmentPostProcessor, Ordered {
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
Map<String, Object> ignoredInterfaces = Maps.newHashMap();
ignoredInterfaces.put("spring.cloud.inetutils.ignoredInterfaces", Lists.newArrayList(".*"));
SystemEnvironmentPropertySource systemEnvironmentPropertySource = new SystemEnvironmentPropertySource("systemEnvironment", ignoredInterfaces);
environment.getPropertySources().addLast(systemEnvironmentPropertySource);
}
@Override
public int getOrder() {
return ConfigFileApplicationListener.DEFAULT_ORDER - 2;
}
}
还要创建META-INF/spring.factories文件
org.springframework.boot.env.EnvironmentPostProcessor=\
上述类名