Dubbo 服务 IP 注册错误踩坑经历

公司最近新建一个机房,需要将现有系统同步部署到新机房,部署完成之后,两地机房同时对提供服务。系统架构如下图:
这个系统当前对外采用 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 地址查找顺序。

Copy
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

查找顺序如图所示:
 
1419561-20200217072028228-1050667355.jpguploading.4e448015.gif转存失败重新上传取消
解析过程,Dubbo 将会过滤无用 IP,过滤规则如下:
 
下面将结合图示讲解查找顺序,只要其中一步读取 IP 符合上述规则,方法就会返回。
第一步将会调用 ServiceConfig#getValueFromConfig 从 environment variables 或 java system properties 配置 IP 地址。
 
这种方式通过在 JVM 启动参数中显示指定 IP 。

Copy
-DDUBBO_IP_TO_BIND=1.2.3.4

第二步通过读取 Dubbo 配置文件配置变量获取 IP。

Copy
<!-- 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 启动参数中加入如下配置

Copy
-DDUBBO_IP_TO_BIND=1.2.3.4

配置方式二:
在 /etc/hosts 设置 hostname 对应的 IP。
配置方式三:
Dubbo 配置文件显示指定 IP。

Copy
<!-- protocol 指定整个 Dubbo 应用服务默认 IP --><dubbo:protocol host="1.2.3.4"/><!-- provider 指定 Dubbo 应用具体某个服务默认 IP --><dubbo:provider host="1.2.3.4"/>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值