微服務(wù)遠(yuǎn)程辦公 VPN 環(huán)境下 Dubbo + Redis 啟動(dòng)失敗排查實(shí)錄
技術(shù)棧:SpringBoot 3.5.8 + Dubbo 3.3.6 + Nacos 2.5.1 + Redis + RuoYi-Cloud-Plus
問(wèn)題現(xiàn)象
在公司內(nèi)網(wǎng)開(kāi)發(fā)機(jī)可正常啟動(dòng)微服務(wù),在家通過(guò) VPN 連接公司網(wǎng)絡(luò)后,同樣的代碼啟動(dòng)失敗,控制臺(tái)報(bào)錯(cuò):
[DUBBO] Failed to get DUBBO_GROUP:mapping:xxx from redis, cause: Failed to connect to any host resolved for DNS name.
dubbo version: 3.3.6, current host: 10.125.59.225
redis.clients.jedis.exceptions.JedisConnectionException: Failed to connect to any host resolved for DNS name.
Suppressed: java.net.SocketTimeoutException: Connect timed out
根因分析
排查發(fā)現(xiàn)存在 兩個(gè)獨(dú)立問(wèn)題,疊加導(dǎo)致了啟動(dòng)失敗:
問(wèn)題一:Dubbo metadata-report Redis 連接超時(shí)
Dubbo 的元數(shù)據(jù)中心(metadata-report)使用 Redis 存儲(chǔ),配置鏈路如下:
common-dubbo.yml (jar內(nèi)置):
dubbo.metadata-report.timeout: ${spring.data.redis.timeout}
↓ 引用
Nacos application-common.yml (遠(yuǎn)程配置):
spring.data.redis.timeout: 11 ← 僅 11 毫秒!
在公司內(nèi)網(wǎng),Redis 延遲 <1ms,11ms 勉強(qiáng)夠用;VPN 環(huán)境延遲 60-140ms,11ms 根本無(wú)法完成 TCP 三次握手,連接必定超時(shí)。
注意:用
redis-cli手動(dòng)連接是正常的,因?yàn)?redis-cli默認(rèn)超時(shí)遠(yuǎn)大于 11ms,不能以此判斷 Java 程序也能連上。
問(wèn)題二:Dubbo 注冊(cè)了錯(cuò)誤的 IP(多網(wǎng)卡選擇問(wèn)題)
本機(jī)存在多塊網(wǎng)卡:
| 網(wǎng)卡 | IP | 說(shuō)明 |
|---|---|---|
| WLAN | 10.125.59.225 | WiFi,Dubbo 錯(cuò)誤選中 |
| 本地連接*3 | 192.168.100.7 | VPN 通道 |
| vEthernet (Default Switch) | 172.20.176.1 | Docker/Hyper-V |
| vEthernet (WSL) | 172.28.224.1 | WSL |
框架內(nèi)置的 CustomBeanFactoryPostProcessor 通過(guò) Spring InetUtils.findFirstNonLoopbackAddress() 自動(dòng)選 IP,選到了 WiFi 的 10.125.59.225,而公司內(nèi)網(wǎng)無(wú)法路由到該 IP。
Nacos 遠(yuǎn)程配置中 spring.cloud.inetutils.preferred-networks 被注釋為空,無(wú)法指導(dǎo)正確的網(wǎng)卡選擇。
為什么本地 application.yml 覆蓋無(wú)效?
Spring Cloud Nacos 配置優(yōu)先級(jí):JVM 系統(tǒng)屬性 > Nacos 遠(yuǎn)程配置 > 本地 application.yml
本地 yml 中加的 spring.data.redis.timeout: 30000 和 spring.cloud.inetutils.preferred-networks: 192.168 都被 Nacos 遠(yuǎn)程配置覆蓋了,不會(huì)生效。
解決方案
在 IDEA 的 Run Configuration → VM options 中添加 JVM 啟動(dòng)參數(shù):
-Ddubbo.ip.to.registry=192.168.100.7 -Dspring.data.redis.timeout=30000
參數(shù)說(shuō)明
| JVM 參數(shù) | 解決的問(wèn)題 | 原理 |
|---|---|---|
-Ddubbo.ip.to.registry=192.168.100.7 |
指定 Dubbo 注冊(cè) IP | 框架 CustomBeanFactoryPostProcessor 第39行優(yōu)先檢查此系統(tǒng)屬性,已有值則跳過(guò)自動(dòng)選 IP |
-Dspring.data.redis.timeout=30000 |
Redis 超時(shí)改為 30s | 覆蓋 Nacos 上的 timeout: 11(11ms),適配 VPN 高延遲 |
不需要 -Dspring.cloud.inetutils.preferred-networks 和 -Ddubbo.protocol.host,因?yàn)?dubbo.ip.to.registry 已經(jīng)直接鎖定 IP。
IDEA 配置步驟
- Run → Edit Configurations...
- 選擇對(duì)應(yīng)微服務(wù)的啟動(dòng)配置
- VM options 中填入上述參數(shù)
- Apply → OK → 重新啟動(dòng)
適用范圍
| 場(chǎng)景 | 是否適用 |
|---|---|
| 遠(yuǎn)程辦公 VPN 連接公司內(nèi)網(wǎng)開(kāi)發(fā) | 適用 |
| 多網(wǎng)卡環(huán)境(WiFi + VPN + Docker + WSL) | 適用 |
| Dubbo 3.x + Redis 元數(shù)據(jù)中心 + Nacos 配置中心架構(gòu) | 適用 |
| Dubbo 2.x |
dubbo.ip.to.registry 同樣適用 |
回到辦公室后
刪掉 VM options 中的參數(shù)即可,內(nèi)網(wǎng)環(huán)境下無(wú)需這些覆蓋。
關(guān)鍵排查思路總結(jié)
-
報(bào)錯(cuò)信息要細(xì)看:
SocketTimeoutException: Connect timed out說(shuō)明是超時(shí)而非網(wǎng)絡(luò)不通,redis-cli能連 ≠ Java 程序也能連 - 配置優(yōu)先級(jí)要清楚:Nacos 遠(yuǎn)程配置 > 本地 yml,本地覆蓋可能被"悄悄"覆蓋掉
- 多網(wǎng)卡是常見(jiàn)坑:VPN 環(huán)境下網(wǎng)卡數(shù)量翻倍,Dubbo/Spring 自動(dòng)選 IP 容易選錯(cuò)
- JVM -D 參數(shù)最可靠:當(dāng)配置優(yōu)先級(jí)混亂時(shí),JVM 系統(tǒng)屬性是最簡(jiǎn)單有效的覆蓋手段