Eureka在有虚拟网卡的情况下获取正确的IP
发现问题
最近项目在Eureka注册时,发现一个问题:注册的IP地址不是 192.168.0.XXX 的网络IP,而是另外一个网段的地址,如图
通过 ipconfig 命令查看本机的IP地址发现,该IP是本机虚拟网卡VMnet8的地址。
X:\Users\Keats>ipconfigWindows IP 配置以太网适配器 以太网:连接特定的 DNS 后缀 . . . . . . . :IPv4 地址 . . . . . . . . . . . . : 192.168.0.234子网掩码 . . . . . . . . . . . . : 255.255.255.0默认网关. . . . . . . . . . . . . : 192.168.0.1以太网适配器 VMware Network Adapter VMnet1:连接特定的 DNS 后缀 . . . . . . . :IPv4 地址 . . . . . . . . . . . . : 192.168.87.1子网掩码 . . . . . . . . . . . . : 255.255.255.0默认网关. . . . . . . . . . . . . :以太网适配器 VMware Network Adapter VMnet8:连接特定的 DNS 后缀 . . . . . . . :IPv4 地址 . . . . . . . . . . . . : 192.168.29.1子网掩码 . . . . . . . . . . . . : 255.255.255.0默认网关. . . . . . . . . . . . . :
问题现象
Eureka管理页面注册列表展示的IP地址非局域网IP地址,是虚拟机的虚拟IP地址
可能引起的问题
多人开发时,同事通过Feign调用接口,无法正确匹配IP地址,从而导致接口调用失败。
尝试解决
通过百度查找,提供了该解决方案:在 yml 文件中添加一下的配置,以达到忽略指定网卡的目的
spring:cloud:inetutils:ignored-interfaces: ## 忽略网卡- VMware.*
可是当我添加该配置后,发现仍不起作用!页面上显示的instance-id 还是 192.168.29.1:8083 。这就很难受了
刨根问底
于是我想能不能跑一跑Spring的启动代码,看看他到底是怎么取IP的。首先从Eureka自动配置类EurekaClientAutoConfiguration入手
@Bean
@ConditionalOnMissingBean(value = EurekaInstanceConfig.class, search = SearchStrategy.CURRENT)
public EurekaInstanceConfigBean eurekaInstanceConfigBean(InetUtils inetUtils,ManagementMetadataProvider managementMetadataProvider) {String hostname = getProperty("eureka.instance.hostname");// 是否使用IP地址注册。这里就是从配置文件寻值,没找到就用默认值 falseboolean preferIpAddress = Boolean.parseBoolean(getProperty("eureka.instance.prefer-ip-address"));// 获取配置的IP地址String ipAddress = getProperty("eureka.instance.ip-address");instance.setPreferIpAddress(preferIpAddress);if (StringUtils.hasText(ipAddress)) {instance.setIpAddress(ipAddress);}return instance;
}
这里可以看到,Eureka并没有自己直接去系统获取IP地址,而是通过Spring的InetUtils类的findFirstNonLoopbackHostInfo来设置IP地址
public EurekaInstanceConfigBean(InetUtils inetUtils) {this.inetUtils = inetUtils;this.hostInfo = this.inetUtils.findFirstNonLoopbackHostInfo();this.ipAddress = this.hostInfo.getIpAddress();this.hostname = this.hostInfo.getHostname();
}
接着看看findFirstNonLoopbackHostInfo()方法的代码。我在本地Debug跑的时候,项目启动该类会被调用两次,一次没有读取配置文件,项目启动Banner也没有打印,第二次配置文件已经读取。启动日志也打印了一部分。这里原因留个坑
public InetAddress findFirstNonLoopbackAddress() {InetAddress result = null;try {int lowest = Integer.MAX_VALUE;for (Enumeration<NetworkInterface> nics = NetworkInterface.getNetworkInterfaces(); nics.hasMoreElements();) {NetworkInterface ifc = nics.nextElement();// 该网络接口是否启用并正在运行。调用的是native方法if (ifc.isUp()) {log.trace("Testing interface: " + ifc.getDisplayName());if (ifc.getIndex() < lowest || result == null) {lowest = ifc.getIndex();}else if (result != null) {continue;}// 该网卡名称不在忽略范围内// @formatter:offif (!ignoreInterface(ifc.getDisplayName())) {// 遍历IP地址for (Enumeration<InetAddress> addrs = ifc.getInetAddresses(); addrs.hasMoreElements();) {InetAddress address = addrs.nextElement();// 找到 IPV4 且不是回环地址(127.0.0.1) 且是优先选择的地址if (address instanceof Inet4Address&& !address.isLoopbackAddress()&& isPreferredAddress(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;}
从上面的代码及注释可以看到,SpringCloud选择IP的原则是:选择已启动网卡的第一个不在忽略范围且不是回环地址(127.0.0.1)且是优先选择地址的IPV4地址
那么我们想要重定义其所选的IP地址,就需要从忽略范围 和 是否是优先选择地址来做了。
判断是否在忽略范围的代码
由该段代码知,要忽略的网口集合需要从 IgnoredInterfaces 这个属性中获得,那这个属性的值是什么?怎么配置呢?
/** for testing */ boolean ignoreInterface(String interfaceName) {// 遍历IgnoredInterfaces属性集合,该集合内是忽略的网口名字的正则表达式形式for (String regex : this.properties.getIgnoredInterfaces()) {if (interfaceName.matches(regex)) {log.trace("Ignoring interface: " + interfaceName);return true;}}return false;
}
判断是否是首选地址的代码
/** for testing */ boolean isPreferredAddress(InetAddress address) {// 如果配置了仅使用本地接口,则当该InetAddress是本地站点地址时返回if (this.properties.isUseOnlySiteLocalInterfaces()) {final boolean siteLocalAddress = address.isSiteLocalAddress();if (!siteLocalAddress) {log.trace("Ignoring address: " + address.getHostAddress());}return siteLocalAddress;}// 如果preferredNetworks列表没有配置,则所有地址返回Truefinal List<String> preferredNetworks = this.properties.getPreferredNetworks();if (preferredNetworks.isEmpty()) {return true;}// 如果配置了,则返回符合正则的地址for (String regex : preferredNetworks) {final String hostAddress = address.getHostAddress();if (hostAddress.matches(regex) || hostAddress.startsWith(regex)) {return true;}}log.trace("Ignoring address: " + address.getHostAddress());return false;
}
结论
- eureka 显示的 instance-id 有两种值,通过 prefer-ip-address 的值来选择
- ip:端口 true
- hostname 主机名 false(默认)
- 当 prefer-ip-address 的值为 true 时,eureka 取这个值:eureka.client.instance-id
- 配置文件中的: eureka.client.instance-id 。可以配置成自己手写的值,也可以自动获取,通过 ${spring.cloud.client.ip-address}
Eureka在有虚拟网卡的情况下获取正确的IP相关推荐
- 使用nginx代理的情况下获取用户真实IP
##1.背景知识 1.1. 前提知识点: 还有nginx中的几个变量: remote_addr 代表客户端的IP,但它的值不是由客户端提供的,而是服务端根据客户端的ip指定的,当你的浏览器访问某个网站 ...
- qt获取本机全部ipv4_QT5下获取本机IP地址、计算机名、网络连接名、MAC地址、子网掩码、广播地址...
获取主机名称 /* * 名称:get_localmachine_name * 功能:获取本机机器名称 * 参数:no * 返回:QString */ QString CafesClient::get_ ...
- python安装包_在python官网打不开的情况下获取获取官方最新安装包
不知道有没有朋友在下载python最新安装包的时候,打不开python官网,我是遇见过,就像我们找东西时一样,需要的时候网站打不开,不需要了秒开,后来小编查阅各种资料,咨询了好几个大佬,终于得知了一个 ...
- 如何在没有导入excel的情况下获取excel中的测试数据
如何在没有导入excel的情况下获取excel中的测试数据 Set oExcel = CreateObject("excel.application") '创建excel对象 oE ...
- springboot定时任务未登录情况下获取用户信息报错解决方案
解决org.apache.shiro.UnavailableSecurityManagerException: No SecurityManager accessible to the calling ...
- 神兵利器 - 在没有任何权限的情况下获取任何 Microsoft Windows 用户密码
神兵利器 - 在没有任何权限的情况下获取任何 Microsoft Windows 用户密码. 项目地址:https://github.com/DarkCoderSc/win-brute-logon 目 ...
- 如何在python官网打不开的情况下获取获取官方最新安装包
不知道有没有朋友在下载python最新安装包的时候,打不开python官网,小编我是遇见过,就像我们找东西时一样,需要的时候网站打不开,不需要了秒开,后来小编查阅各种资料,咨询了好几个大佬,终于得知了 ...
- 无线网dhcp服务器租期,缺省情况下,DHCP服务器分配IP地址的租期为()。
管理员在Router上进行了如下配置,那么连接在该路由器的G1/0/0接口下的一-台主机,能够通过DHCP获取到什么样的IP地址(). [Router]ippoolpooll TRouter-ippo ...
- Nginx在多层代理下获取真实客户端IP地址
最近在研究nginx中如何获取真实客户端IP的方法.众所周知,在编译Nginx时,可通过添加http_realip_module模块来获取真实客户端IP地址.何为真实IP地址呢?请看下图,既获取到的真 ...
最新文章
- canvas动画特效 之 星空
- SpringMvc 事务的注解配置、实现、挂起
- 让ie8、ie9支持媒体查询
- 图论(八)最小生成树
- [再寄小读者之数学篇](2014-06-03 华罗庚等式)
- 利用python爬虫(part1)--urllib.request模块
- 修改Jupyter的工作空间
- 使用XMLConfiguration解析xml,properties等相应信息
- 程序员修神之路--高并发下如何缩短响应时间
- 在阿里云上试用 Knative
- [Flink] Flink运行报错The number of requested virtual cores for application master
- 闲说HeartBeat心跳包和TCP协议的KeepAlive机制
- Git:clone时报错403
- 32个参数累加_「机械设计教程」滚珠丝杠选型过程中考虑的9个参数
- 硅谷钢铁侠的的传奇人生
- 无线串口服务器规模,无线串口服务器
- 机器学习笔记 - 时间序列的季节性
- 禁漫排行榜周目公告版_华泰证券手机版下载-华泰证券涨乐财富通手机版下载V7.5.0安卓版...
- Outlook2019添加126邮箱方法
- 笔记本电脑怎么启用c语言,win7笔记本启动0xc000014c信息,如何解决的教程
热门文章
- 关于HtmlCxx对,C++ 解析,编辑,重新生成HTML的
- mysql ogg kafka_ogg实时同步到Kafka
- JavaWeb:(二)HTML
- Resolving LVM and Hard Disk PVID Issues 解决LVM和硬盘PVID的问题
- 计算机不能进入桌面,电脑开机后无法进入桌面怎么办?
- GetLastError()返回值含义
- 无线AP 的频段(2.4GHZ or 5GHz)
- 【转】dd命令详解及利用dd测试磁盘性能
- 基于百度地图api实现计算目标点与自身位置的距离(js)
- RestfulToolKit:便捷的 IDEA 接口测试神器
- 使用nginx代理的情况下获取用户真实IP