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,過濾規則如下:

image-20200201203655297

下面將結合圖示講解查找順序,只要其中一步讀取 IP 符合上述規則,方法就會返回。

第一步將會調用 ServiceConfig#getValueFromConfigenvironment variablesjava 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。但是現實還是很殘酷,真實環境下機器可能存在多網卡,內外網 IPVPN ,或者應用采用 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


免責聲明!

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



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