Dubbo 获取本地ip错误

前言

我们因为安全漏洞将dubbo 升级到2.7.15 版本,当环境中存在docker 部署的时候。dubbo 获取本机ip将会变成docker0的地址。

实践

我们查看dubbo 获取ip地址的源码org.apache.dubbo.common.utils.NetUtils#getLocalAddress0来获取本地地址。
可以看到关键在于findNetworkInterface() 获取到网卡的地址
Dubbo 获取本地ip错误_第1张图片
我们将findNetworkInterface 这个方法贴出来,看到要获取networkInterface 分了三步,

public static NetworkInterface findNetworkInterface() {

        List validNetworkInterfaces = emptyList();
        try {
            validNetworkInterfaces = getValidNetworkInterfaces();
        } catch (Throwable e) {
            logger.warn(e);
        }

        NetworkInterface result = null;

        // Try to find the preferred one
        //一、查看所有网卡中是否isPreferredNetworkInterface(networkInterface) 是否优先网卡
        //判断是否有是优先网卡通过名字来比对的
        //String preferredNetworkInterface = System.getProperty(DUBBO_PREFERRED_NETWORK_INTERFACE);
       // return Objects.equals(networkInterface.getDisplayName(), preferredNetworkInterface);
        for (NetworkInterface networkInterface : validNetworkInterfaces) {
            if (isPreferredNetworkInterface(networkInterface)) {
                result = networkInterface;
                break;
            }
        }

        if (result == null) { // If not found, try to get the first one
            for (NetworkInterface networkInterface : validNetworkInterfaces) {
                Enumeration addresses = networkInterface.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    Optional addressOp = toValidAddress(addresses.nextElement());
                    if (addressOp.isPresent()) {
                        try {
                            if (addressOp.get().isReachable(100)) {
                                return networkInterface;
                            }
                        } catch (IOException e) {
                            // ignore
                        }
                    }
                }
            }
        }

        if (result == null) {
            result = first(validNetworkInterfaces);
        }

        return result;
    }

    public static String getHostName(String address) {
        try {
            int i = address.indexOf(':');
            if (i > -1) {
                address = address.substring(0, i);
            }
            String hostname = HOST_NAME_CACHE.get(address);
            if (hostname != null && hostname.length() > 0) {
                return hostname;
            }
            InetAddress inetAddress = InetAddress.getByName(address);
            if (inetAddress != null) {
                hostname = inetAddress.getHostName();
                HOST_NAME_CACHE.put(address, hostname);
                return hostname;
            }
        } catch (Throwable e) {
            // ignore
        }
        return address;
    }

一、查看所有网卡中是否isPreferredNetworkInterface(networkInterface) 是否优先网卡
判断是否有是优先网卡通过名字来比对的

二、没有配置优先网卡或者配置优先网卡不存在则会
获取到当0.1s网络可达的网卡

三、如果前面条件都不成功
直接获取i存在的网卡

根据上面三个判断条件如果获取网卡不是自己想要的,可以通过配置优先网卡来获取自己想要网卡。

String preferredNetworkInterface = System.getProperty(DUBBO_PREFERRED_NETWORK_INTERFACE);
return Objects.equals(networkInterface.getDisplayName(), preferredNetworkInterface);

DUBBO_PREFERRED_NETWORK_INTERFACE 的值是dubbo.network.interface.preferred
那么就可以在启动命令中或者yml配置网卡名称

-Ddubbo.network.interface.preferred=eth0 (启动命令中添加)

yml配置优先网卡名称:

dubbo:
network:
interface:
preferred: eth0

同时也可以通过排除忽略网卡排除错误网卡
-Ddubbo.network.interface.ignored=docker0

yml配置优先网卡名称:

dubbo:
network:
interface:
ignored: docker0

你可能感兴趣的:(java,java,后端)