问题描述
线上服务器安装docker后,出现多的网卡,导致dubbo注册的时候,现在ip的不正确的情况
问题查找
原因是因为我在安装完docker后,服务器机器上配置了很多的虚拟IP,这样错误的解析结果导致dubbo服务一直无法被访问到,调用方一直在报错。
造成这种结果的原因是什么呢?既然是注册的ip有问题,那么我们可以先看下dubbo解析IP地址的源码,ServiceConfig类下的doExportUrlsFor1Protocol方法:
private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
...................省略......................
//1.先从ProtocolConfig中获取host
String host = protocolConfig.getHost();
//2.如果host为空,再从ProviderConfig中获取host
if (provider != null && (host == null || host.length() == 0)) {
host = provider.getHost();
}
boolean anyhost = false;
//3.验证host是否为本地可用的host,如果是本地host(0.0.0.0或者localhost或者127.0.0.1之类)则继续解析
if (NetUtils.isInvalidLocalHost(host)) {
anyhost = true;
try {
//4.通过InetAddress的方式获取host,默认读取本机hosts中hostname对应的ip地址
host = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
logger.warn(e.getMessage(), e);
}
if (NetUtils.isInvalidLocalHost(host)) {
if (registryURLs != null && registryURLs.size() > 0) {
for (URL registryURL : registryURLs) {
try {
Socket socket = new Socket();
try {
//5.通过SocketAddress的方式获取host,一般情况下解析到此处就可以得到正确的本地ip,但是因为我配置了很多虚拟ip,所以这里导致了解析异常
SocketAddress addr = new InetSocketAddress(registryURL.getHost(), registryURL.getPort());
socket.connect(addr, 1000);
host = socket.getLocalAddress().getHostAddress();
break;
} finally {
try {
socket.close();
} catch (Throwable e) {}
}
} catch (Exception e) {
logger.warn(e.getMessage(), e);
}
}
}
//6.遍历本地网卡,返回一个合理的host
if (NetUtils.isInvalidLocalHost(host)) {
host = NetUtils.getLocalHost();
}
}
}
..............省略..............
}
dubbo解析IP地址的步骤如下:
- 先从ProtocolConfig中取host
- 再从ProviderConfig中取host
- 若取出的是本地host, 则继续取host
- 通过InetAddress.getLocalHost().getHostAddress();的方式获取Host
- 通过Socket的方式尝试连接到注册中心,通过socket.getLocalAddress().getHostAddress()获取Host
- 遍历本地网卡, 返回第一个合理的Host
解决方法
-
配置本机主机名,在hosts中加入本机名和本机物理ip的映射关系(最简单,不用动任何配置)
-
如果是docker启动相关应用,可以在run时,加入-e DUBBO_IP_TO_REGISTRY = ip地址
-
jar方式启动程序,添加启动参数-D DUBBO_IP_TO_REGISTRY = ip地址
备注: 在2、3的方式中,其实原理都是类似,都是通过配置参数将ip设置成我们想要设置的ip地址
评论区