Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1019958
  • 博文数量: 87
  • 博客积分: 3324
  • 博客等级: 中校
  • 技术积分: 1003
  • 用 户 组: 普通用户
  • 注册时间: 2006-05-17 11:37
文章分类

全部博文(87)

文章存档

2014年(3)

2013年(5)

2012年(21)

2011年(13)

2010年(7)

2009年(9)

2008年(4)

2007年(14)

2006年(11)

分类: Java

2014-11-07 16:27:06

今天在跑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函数,可以看一下。

阅读(11541) | 评论(2) | 转发(0) |
1

上一篇:Linux tree 命令乱码

下一篇:没有了

给主人留下些什么吧!~~

iwlk2015-04-13 15:47:55

同意, 在Linux 下 getHostName 经常是:localhost.localdomain   getHostAddress的结果就是:127.0.0.1  晕!

vwyuheng2015-03-23 17:09:42

这个问题你是怎么解决的最后?