macos本地启动dubbo2.5.3 获取不到服务的问题

2022年5月14日 804点热度 0人点赞 0条评论

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&timestamp=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&timestamp=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,就导致出现了获取不到服务的情况。

总结:

遇到问题会走很多弯路。但是一步步查下去能学到很多东西。最重要的是基础非常重要!

管理员

这个人很懒,什么都没留下

文章评论