Hosts 地址錯誤,導致 Dubbo 提供者服務 IP 選擇錯誤的問題 ...
個人博客地址 studyidea.cn,點擊查看更多原創文章
踩坑
公司最近新建一個機房,需要將現有系統同步部署到新機房,部署完成之後,兩地機房同時對提供服務。系統架構如下圖:
這個系統當前對外採用 Restful
介面,內部遠程採用 Dubbo
,服務註冊中心使用 zookeeper
。服務當前設定只會調用本機房內服務。
原先服務都在 A 機房,B 機房為新建機房。B 機房部署完成之後,需要測試 B 機房系統可用性。生產測試的發現 B 機房竟然調用 A 機房服務。
A/B 機房網路互相打通,可以互相訪問
通過排查 B 機房服務日誌,發現 Service B
一個服務節點註冊 IP 解析錯誤,將 B 機房機器 IP 解析成 A 機房機器 IP。
於是當測試流量進入 B 機房時,openapi
服務通過註冊中心獲取到錯誤的 Service B
服務地址,從而調用了 A 機房的服務。調用方式簡化成如下圖。
知識點:Dubbo 服務提供者啟動時將會將服務地址(IP+埠)註冊到註冊中心,消費者啟動時將會通過註冊中心獲取服務提供者地址(IP+埠),後續服務調用將會直接通過服務地址直接調用。
問題分析
Debug Dubbo
源碼,定位到 IP
解析代碼,位於 ServiceConfig#findConfigedHosts
,源碼如下:
Dubbo 版本為 2.6.7
這個方法源碼比較長,看起來比較費勁,不過好在這個方法註釋上已經寫明白 IP
地址查找順序。
Register & bind IP address for service provider, can be configured separately. Configuration priority: environment variables -> java system properties -> host property in config file -> /etc/hosts -> default network address -> first available network address
查找順序如圖所示:
解析過程,Dubbo
將會過濾無用 IP,過濾規則如下:
下麵將結合圖示講解查找順序,只要其中一步讀取 IP 符合上述規則,方法就會返回。
第一步將會調用 ServiceConfig#getValueFromConfig
從 environment variables
或 java system properties
配置 IP 地址。
這種方式通過在 JVM
啟動參數中顯示指定 IP 。
-DDUBBO_IP_TO_BIND=1.2.3.4
第二步通過讀取 Dubbo
配置文件配置變數獲取 IP。
<!-- protocol 指定整個 Dubbo 應用服務預設 IP -->
<dubbo:protocol host="1.2.3.4"/>
<!-- provider 指定 Dubbo 應用具體某個服務預設 IP -->
<dubbo:provider host="1.2.3.4"/>
第三步通過調用 InetAddress.getLocalHost().getHostAddress()
獲取本地 IP。該方法將會獲取機器 hostname
,然後再在 /etc/hosts
配置文件中查找 hostname
對應的配置 IP。
第四步通過 socket
連接註冊中心從而獲取本機 IP。
如果上述幾步都不成功,Dubbo 將會輪詢本機所有網卡,直到找到合適的 IP 地址。
問題原因
通過排查上述幾個規則,最後發現本地 /etc/hosts
文件 IP 配置錯誤, hostname
配置成了 A 機房的 IP 。
總結
Dubbo 在 IP 解析上花費很大功夫,最大程度上幫我們自動獲取正確 IP。但是現實還是很殘酷,真實環境下機器可能存在多網卡,內外網 IP,VPN ,或者應用採用 Docker 部署,這些情況下Dubbo
有可能就會獲取到錯誤 IP,從而導致消費者調用失敗。如果真遇到這種情況,讀者首先通過上面順序排查 IP 讀取來源,若最後確定 IP 讀取自網卡 。這種情況下就只能根據下麵幾種方式顯示指定 IP。
配置方式一:
在 JVM
啟動參數中加入如下配置
-DDUBBO_IP_TO_BIND=1.2.3.4
配置方式二:
在 /etc/hosts
設置 hostname
對應的 IP。
配置方式三:
Dubbo
配置文件顯示指定 IP。
<!-- protocol 指定整個 Dubbo 應用服務預設 IP -->
<dubbo:protocol host="1.2.3.4"/>
<!-- provider 指定 Dubbo 應用具體某個服務預設 IP -->
<dubbo:provider host="1.2.3.4"/>
隨便聊聊
這次的問題其實不大,就是 hosts 文件配置錯誤,但是整個查找問題的過程還是值得學習的,深入到了源碼層面,跟蹤代碼,最終發現問題。生產出現問題,如何第一時間定位到問題,這是一門學問。我們不僅要瞭解業務代碼,也要清楚框架的原理。每一次的踩坑經歷,都是一次考驗,經歷的多了,經驗自然也會多了,這也許就是資深程式員與初級程式員差別。
幫助鏈接
https://dubbo.apache.org/zh-cn/blog/dubbo-network-interfaces.html
歡迎關註我的公眾號:程式通事,獲得日常乾貨推送。如果您對我的專題內容感興趣,也可以關註我的博客:studyidea.cn