坑爹的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函數,可以看一下。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM