坑爹的InetAddress getLocalHost函数
今天在跑dubbo 的 DemoService 2.5.4-SNAPSHOT版本的时候,遇到到一个奇怪的问题。consumer怎么都连接不上provider的服务。最后才发现是由于dubbo自 己实现的检测本地IP地址代码不够强壮造成的。你这里的provider实际上是运行在A地址上,但是dubbo检测到本地的IP地址是B,然后他在 zookeeper上注册自己的服务地址的时候,用的是这个B这个IP地址,那么当consumer连接到zookeeper上的时候,查询到 DemoService是在B上的,显然这个IP地址上并没有这样的dubbo服务,那么这个consumer就肯定不能成功。
为什么dubbo检测本地IP地址的结果是错的,因为dubbo检测本地IP地址的策略是先调用InetAddress.getLocalHost,如果
该方法返回一个合法的地址,则直接认为是本地的IP地址,否则会枚举本地所有网卡,并返回第一个合法的IP地址作为本地地址。
坑爹的就是InetAddress.getLocalHost返回了一个错误的IP地址。为什么这个函数会返回一个错误的地址,因为这个函数的原理是通过
获取本机的hostname,然后对此hostname做解析,从而获取IP地址的。那么问题来了,如果在本机的/etc/hosts文件里对这个主机名
指向了一个错误的IP地址,那么InetAddress.getLocalHost就会返回这个错误的IP地址。当然如果你的hostname是到DNS
去解析的,碰巧DNS上的信息也是错的,也同样是悲惨结局。
遇到同样问题的人,可以先检查下hosts文件的设置里面A地址指向哪里了,然后看一下DNS解析出的地址。当然如果dubbo的代码检查一下,这个返回
的地址,是不是真的是本机的IP地址,也不会出现这个问题了,归根结底还是dubbo的卡发人员太相信InetAddress.getLocalHost
了,这货自己应该确保不会出现这样的乌龙事件的。你返回一个不是本机的IP地址作为本机的IP地址,这个在语义上就错误了。不管你用了多么愚蠢的算法,结
果就是不应该返回一个不是本地的IP地址作为本地的地址,不是吗?否则还叫什么狗屁get local host!!!
我为什么说InetAddress.getLocalHost的算法是愚蠢的,是因为这个尽管可能会被hosts文件和DNS误导,但是显然这两个地方都
不是本机IP地址的权威获取处,权威获取处是网卡本身的配置信息。即便你要使用一个不靠谱来源的信息,你至少跟本机的网卡地址做一下校验嘛!如果你实在是
不知道怎么获取,抛出个异常说明一下你的无能为力,大家也是可以接受的嘛!犯不着给个错误的信息,让这么多人掉坑里,浪费时间,对不对?
最后,dubbo检测本地地址的代码位于:
dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/NetUtils.java里的getLocalAddress函数,可以看一下。
坑爹的InetAddress getLocalHost函数的更多相关文章
- InetAddress.getLocalHost() 执行很慢?
背景介绍 某次在 SpringBoot 2.2.0 项目的一个配置类中引入了这么一行代码: InetAddress.getLocalHost().getHostAddress() 导致项目启动明显变慢 ...
- at java.net.InetAddress.getLocalHost(InetAddress.java:1475)
今天在centos 安装hadoop安装完成后执行wordcount的时候报如下错误: at java.net.InetAddress.getLocalHost(InetAddress.java:14 ...
- mac系统InetAddress.getLocalHost().getHostAddress() 很慢
java.net.InetAddress.getLocalHost() 这个调用在新版的mac os中可能会耗时很久. 解决办法有两种: 1. 就是把本机的hostname 添加到 hosts 中,例 ...
- jmeter的新增函数说明
本文算是对<零成本实现Web性能测试:基于Apache JMeter>中的<详解JMeter函数和变量>进行狗尾续貂哈,因为最近版本的jmeter增加了几个新函数,在原书中没有 ...
- Spark远程调试函数
Spark远程调试函数 1.sendInfo 该函数用于分布式程序的调试,非常方便,在spark的rdd操作中嵌入sendInfo,启动nc服务器后,可以收集到所有需要的运行时信息,该函数可以捕获ho ...
- java:网络编程(InetAddress,InetSocketAddress,URL,TCP(Socket与SeverSocket),TCP与UDP的区别)
InerAddress: /**IP地址:在网络上唯一标示一台计算机 * 端口号:标示计算机上不同的应用程序 * java.net.InetAddress类:此类表示互联网协议 (IP) 地址. * ...
- ES6 箭头函数中的 this?你可能想多了(翻译)
箭头函数=>无疑是ES6中最受关注的一个新特性了,通过它可以简写 function 函数表达式,你也可以在各种提及箭头函数的地方看到这样的观点——“=> 就是一个新的 function”. ...
- java中Inetaddress类
InetAddress类 InetAddress类用来封装我们前面讨论的数字式的IP地址和该地址的域名. 你通过一个IP主机名与这个类发生作用,IP主机名比它的IP地址用起来更简便更容易理解. Ine ...
- InetAddress类
InetAddress类是Java对IP地址(包括IPv4和IPv6)的高层表示.大多数其他网络类都要用到这个类,包括Socket,ServerSocket,URL,DatagramSocket,Da ...
随机推荐
- Stackoverflow 珠玑:C#封装重试指定次数的功能
最近写的一个 .NET Core 爬虫里用到了需要多次重试的功能,本着无脑输出的精神,google 了一下,还真给我找到了: public static T Retry<T, TExceptio ...
- Android NDK编译之undefined reference to 'JNI_CreateJavaVM'
利用Android NDK编译动态库,在C文件中调用了两个JNI函数:JNI_GetDefaultJavaVMInitArgs和JNI_CreateJavaVM.编译的时候始终报以下错误: XXX: ...
- ViewPager+Fragment切换卡顿解决办法
1.ViewPager设置预加载 我有4个tag,都不想被销毁,设置预加载个数为3. ViewPager viewPager; viewPager.setOffscreenPageLimit(3); ...
- JMeter—断言(十一)
参考<全栈性能测试修炼宝典JMeter实战>第六章 JMeter 元件详解中第六节断言断言用来对服务器的响应数据做验证,常用的断言是响应断言,支持正则表达式. 一.BeanShell As ...
- Azure 标准与高级托管磁盘存储的相互转换
托管磁盘提供两种存储选项:高级(基于 SSD)和标准(基于 HDD). 它允许基于性能需求在这两个选项之间轻松切换,并保障最短停机时间. 非托管磁盘不具备此功能. 但可以轻松转换为托管磁盘,以便在这两 ...
- SQL Server ->> DAC(Dedicated Administrator Connection)专用管理员连接
专用管理员连接是一种特殊的SQL Server服务器诊断性质的连接,用于在正常或者说标准连接形式无法连接SQL Server服务器的情况下连接到服务器进行服务器性能或者错误诊断.DAC同样支持安全加密 ...
- .net core HttpContext(Http上下文)
在.NET Core中,只有Controller才能直接使用 HttpContext ,其他地方需要通过HttpContextAccessor来访问
- Centos 下添加开机自启动服务和脚本
最近刚玩Centos7的系统,跟Centos6还是很多方面有改变的,这里记录一下怎么在Centos7下添加开机自启动脚本和服务的方法. 1.添加开机自启服务 我这里以docker 服务为例,设置如下两 ...
- Dos命令讲解
目录 一.什么是DOS 二.启动DOS的多种方法 三.DOS的内部命令与外部命令 四.系统环境变量讲解 增加Path环境变量路径 常见的系统环境变量 五.常用的运行命令 六.DOS使用技巧 设置CMD ...
- bash的内置字符串处理工具
bash内置字符串处理工具: 1.字符串切片: ${var:offset:number} 取字符串的子串: ${var: -length} 取字符串的最右侧的length个字符.注意:冒号右侧必须有 ...