1 前言
最近再做一个几年前小的项目,代码都是原来的,突然发现本地启动服务不,提示没有服务提供者。
Failed to invoke the method XXX in the service com.XXX.bsms.service.uums.UumsUserService. Tried 1 times of the providers [172.27.235.77:20880] (1/1) from the registry localhost:2181 on the consumer 172.27.235.77 using the dubbo version 2.5.3. Last error is: Failed to invoke remote method: getUumsUserByLogin, provider: dubbo://172.27.235.77:20880/com.xxx.bsms.service.uums.UumsUserService?anyhost=true&application=b2c &check=false&default.check=false&default.delay=-1&default.retries=0&default.timeout=30000&default.version=1.0.0&delay=-1& dubbo=2.5.3&interface=com.xxx.bsms.service.uums.UumsUserService&methods=getUumsUserByIdList,getUumsUserByLogin,registe, getUumsUserById,insertUumsUser,updateUumsUser,checkUsername,updateUumsUserPassword, getPaginatorUumsUser,getUumsUserByLikeUsername&pid=46381&revision=1.0.0-SNAPSHOT&side=consumer×tamp=16525 33359259&version=1.0.0, cause: message can not send, because channel is closed . url:dubbo://172.27.235.77:20880/com.xxx.bsms.service.uums.UumsUserService?anyhost=true&application=b2c&ch eck=false&codec=dubbo&default. check=false&default.delay=-1&default.retries=0&default.timeout=30000&default.version=1.0.0&delay=-1&dubbo=2.5.3&heartbeat=600 00&interface=com.xxx.bsms.service.uums.UumsUserService&methods=getUumsUserByIdList,getUumsUserByLogin,registe,getUumsUserBy Id,insertUumsUser,updateUumsUser,checkUsername,updateUumsUserPassword,getPaginatorUumsUser,getUumsUserByLikeUsername&pid=4638 1&revision=1.0.0-SNAPSHOT&side=consumer×tamp=1652533359259&version=1.0.0
2 问题查找步骤
1 最初开始查看是zookeeper缓存的问题,结果把zookeeper的服务端都调试了一遍。没有发现问题。
2 然后查看本地IP(最初就应该想到这个问题)
最初看下是172.xxx的ip,奇怪了,我在公司启动的时候就没有,所以才会查看缓存。经过一轮也没发现啥问题。惯性思维作怪。
3 然后调试dubbo服务注册时获取的IP地址
果然发现了眉目,这个ip地址就是本地获取的。获取IP地址代码在getLocalAddress0 中。
com.alibaba.dubbo.common.utils.NetUtils private static InetAddress getLocalAddress0() { InetAddress localAddress = null; try { localAddress = InetAddress.getLocalHost(); if (isValidAddress(localAddress)) { return localAddress; } } catch (Throwable e) { logger.warn("Failed to retriving ip address, " + e.getMessage(), e); } try { //重点在这一行 Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); if (interfaces != null) { while (interfaces.hasMoreElements()) { try { NetworkInterface network = interfaces.nextElement(); Enumeration addresses = network.getInetAddresses(); if (addresses != null) { while (addresses.hasMoreElements()) { try { InetAddress address = addresses.nextElement(); //重点在这一行 if (isValidAddress(address)) { return address; } } catch (Throwable e) { logger.warn("Failed to retriving ip address, " + e.getMessage(), e); } } } } catch (Throwable e) { logger.warn("Failed to retriving ip address, " + e.getMessage(), e); } } } } catch (Throwable e) { logger.warn("Failed to retriving ip address, " + e.getMessage(), e); } logger.error("Could not get local host ip address, will use 127.0.0.1 instead."); return localAddress; } //此方法非常重要 private static boolean isValidAddress(InetAddress address) { if (address == null || address.isLoopbackAddress()) return false; String name = address.getHostAddress(); return (name != null && ! ANYHOST.equals(name) && ! LOCALHOST.equals(name) && IP_PATTERN.matcher(name).matches()); }
定位到了问题,开始查看dubbo修复的版本。果然,引用了2.7.15的包。发现 其注释 @since 2.7.6, choose the {@link NetworkInterface} first。
private static InetAddress getLocalAddress0() { InetAddress localAddress = null; // @since 2.7.6, choose the {@link NetworkInterface} first try { NetworkInterface networkInterface = findNetworkInterface(); Enumeration addresses = networkInterface.getInetAddresses(); while (addresses.hasMoreElements()) { Optional addressOp = toValidAddress(addresses.nextElement()); if (addressOp.isPresent()) { try { if (addressOp.get().isReachable(100)) { return addressOp.get(); } } catch (IOException e) { // ignore } } } } catch (Throwable e) { logger.warn(e); } try { localAddress = InetAddress.getLocalHost(); Optional addressOp = toValidAddress(localAddress); if (addressOp.isPresent()) { return addressOp.get(); } } catch (Throwable e) { logger.warn(e); } return localAddress; }
查看本地IP地址,用2.5.3版本获取的是172.27.235.77,用新的版本获取的是正确的地址。
$ ifconfig lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384 options=1203<RXCSUM,TXCSUM,TXSTATUS,SW_TIMESTAMP> inet 127.0.0.1 netmask 0xff000000 inet6 ::1 prefixlen 128 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 nd6 options=201<PERFORMNUD,DAD> gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280 stf0: flags=0<> mtu 1280 en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 options=400 ether 38:f9:d3:e3:58:2b inet6 fe80::1895:a2ab:1bf4:6931%en0 prefixlen 64 secured scopeid 0x4 inet 192.168.0.101 netmask 0xffffff00 broadcast 192.168.0.255 nd6 options=201<PERFORMNUD,DAD> media: autoselect status: active en1: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500 options=460<TSO4,TSO6,CHANNEL_IO> ether 82:b6:1b:88:4c:01 media: autoselect status: inactive en2: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500 options=460<TSO4,TSO6,CHANNEL_IO> ether 82:b6:1b:88:4c:00 media: autoselect status: inactive bridge0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 options=63<RXCSUM,TXCSUM,TSO4,TSO6> ether 82:b6:1b:88:4c:01 Configuration: id 0:0:0:0:0:0 priority 0 hellotime 0 fwddelay 0 maxage 0 holdcnt 0 proto stp maxaddr 100 timeout 1200 root id 0:0:0:0:0:0 priority 0 ifcost 0 port 0 ipfilter disabled flags 0x0 member: en1 flags=3<LEARNING,DISCOVER> ifmaxaddr 0 port 5 priority 0 path cost 0 member: en2 flags=3<LEARNING,DISCOVER> ifmaxaddr 0 port 6 priority 0 path cost 0 nd6 options=201<PERFORMNUD,DAD> media: status: inactive p2p0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 2304 options=400 ether 0a:f9:d3:e3:58:2b media: autoselect status: inactive awdl0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1484 options=400 ether 8e:ba:ac:f0:4f:5b inet6 fe80::8cba:acff:fef0:4f5b%awdl0 prefixlen 64 scopeid 0x9 nd6 options=201<PERFORMNUD,DAD> media: autoselect status: active llw0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 options=400 ether 8e:ba:ac:f0:4f:5b inet6 fe80::8cba:acff:fef0:4f5b%llw0 prefixlen 64 scopeid 0xa nd6 options=201<PERFORMNUD,DAD> media: autoselect status: active utun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1380 inet6 fe80::ef2e:4243:cf87:5bd2%utun0 prefixlen 64 scopeid 0xb nd6 options=201<PERFORMNUD,DAD> utun1: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 2000 inet6 fe80::46e8:bd52:28e7:46b1%utun1 prefixlen 64 scopeid 0xc nd6 options=201<PERFORMNUD,DAD> utun2: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1000 inet6 fe80::ce81:b1c:bd2c:69e%utun2 prefixlen 64 scopeid 0xd nd6 options=201<PERFORMNUD,DAD> utun3: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1500 inet 172.27.235.77 --> 172.27.232.1 netmask 0xfffffc00
那么172.27.235.77 是怎么来的呢。
utun 是虚拟设备没错,更进一步地,utun 是一种点对点的设备。--> 是一种给人类展示的记号,标明本端地址和对端地址。由于 utun 是点对点的链路,从这端送出的数据一定会到对端,因此对端地址的意义其实是有限的,你可以不必在意。
可以参考如下2个文章:
https://www.zhihu.com/question/267492180/answer/325074960
为什么网关与主机可以不在同一个网段?
https://www.zhihu.com/question/54007586/answer/137515718
原因是我本地启动了VPN,加上dubbo2.5.3的bug,就导致出现了获取不到服务的情况。
总结:
遇到问题会走很多弯路。但是一步步查下去能学到很多东西。最重要的是基础非常重要!
文章评论