zoukankan      html  css  js  c++  java
  • dubbo注册服务IP解析异常及IP解析源码分析

    在使用dubbo注册服务时会遇到IP解析错误导致无法正常访问.
    比如: 本机设置的IP为172.16.11.111, 但实际解析出来的是180.20.174.11
    这样就导致这个Service永远也无法被访问到, 而调用方一直报错.

    当然若发现服务无法访问, 最好先通过dubbo-admin后台排查下注册的服务是否正常.

    IP解析异常时的解决方法:

    • 绑定hostname+ip
        1. 先查看机器的hostname
        2. 修改hosts文件, 增加hostname 172.16.11.111
    
    • 配置nameserver
        排查机器上配置的nameserver是否有问题, 若存在无用的nameserver则直接删掉
    
    • 在dubbo的配置文件中写死host
        <dubbo:protocol host="172.16.11.111"/>
        或者在每个provider中绑定host
        <dubbo:provider host="172.16.11.111">
    

    最好不要用第三种方式, 限制太多. 而且如果这样做了就不支持集群了.
    dubbo的官网也不建议使用这种方式. 请慎用.

    dubbo获取IP源码分析

    
        /**
         * 判断host是否为不可用的本地Host
         */
        public static boolean isInvalidLocalHost(String host) {
            return host == null 
                        || host.length() == 0
                        || host.equalsIgnoreCase("localhost")
                        || host.equals("0.0.0.0")
                        || (LOCAL_IP_PATTERN.matcher(host).matches());
        }
    
        /**
         * 获取本地Host.
         * 若address == null ? "127.0.0.1" : InetAddress.getHostAddress();
         */
        public static String getLocalHost(){
            InetAddress address = getLocalAddress();
            return address == null ? LOCALHOST : address.getHostAddress();
        }
    
        private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
            ...
            ...
            //1. 先从ProtocolConfig中取host. 若没有配置则为null
            String host = protocolConfig.getHost();
    
            //2. 再从ProviderConfig中取host. 若没有配置则为null
            if (provider != null && (host == null || host.length() == 0)) {
                host = provider.getHost();
            }
    
            boolean anyhost = false;
    
            //3. 若取出的是本地host, 则继续取host
            if (NetUtils.isInvalidLocalHost(host)) {
                anyhost = true;
                try {
                    //4. 通过InetAddress的方式获取Host
                    //默认读取本机hosts中hostname对应的IP
                    //如: 你在hosts中配置了 leo 172.16.11.111
                    //则读取的IP就是172.16.11.111
                    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. 通过Socket的方式获取Host
                                    //一般解析到这里, 都会获取到正确的本地IP, 除非你有多网卡, 或者有VPN, 导致无法正常解析.
                                    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
                    //最后一个大招. 当上述都解析不到时, 则会遍历本地网卡.
                    //逐个获取IP, 直到有一个合理的IP为止.
                    if (NetUtils.isInvalidLocalHost(host)) {
                        host = NetUtils.getLocalHost();
                    }
                }
            }
            ...
        }
    
    
        /**
         * 遍历本地网卡,返回第一个合理的IP。
         * @return 本地网卡IP
         */
        public static InetAddress getLocalAddress() {
            if (LOCAL_ADDRESS != null)
                return LOCAL_ADDRESS;
            InetAddress localAddress = getLocalAddress0();
            LOCAL_ADDRESS = localAddress;
            return localAddress;
        }
    
        /**
         * 遍历本地网卡,返回第一个合理的IP。
         * @return 本地网卡IP
         */
        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<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
                if (interfaces != null) {
                    while (interfaces.hasMoreElements()) {
                        try {
                            NetworkInterface network = interfaces.nextElement();
                            Enumeration<InetAddress> 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;
        }
    
  • 相关阅读:
    记一次渗透测试(5)
    记一次渗透实战(一)
    Spring IOC/DI
    Mysql 索引
    Mysql 存储过程
    Mysql 视图
    Mysql 用户和权限
    Mysql 事务
    Mysql 常用函数
    Mysql 子查询
  • 原文地址:https://www.cnblogs.com/leo-li-3046/p/5702479.html
Copyright © 2011-2022 走看看