0


微服务注册到Eureka之后调用不了

前言

前段时间,有同事反馈开发联调环境有个订单服务访问不了,在Eureka页面上点击服务也是链接拒绝,很奇怪,连接访问的ip是一个陌生IP,并不是订单服务部署服务器的ip,后来查看了下服务器网卡信息,发现服务器上挂载了一个新网卡。

而服务注册到Eureka服务端就是172.30.32.16的地址。当时这个ip实际是访问不了的,所以就出现服务注册Eureka成功,但是服务调用不了的现象。

多网卡环境下Eureka服务注册IP的选择问题

对于上面这种问题,一般我们怎么解决呢?这就需要看下Eureka的源码了,Eureka Client的源码在eureka-client模块下,com.netflix.appinfo包下的InstanceInfo类封装了本机信息,其中就包括了IP地址。在Spring Cloud 环境下,Eureka Client并没有自己实现探测本机IP的逻辑,而是交给Spring的InetUtils工具类的findFirstNonLoopbackAddress()方法完成的:

public InetAddress findFirstNonLoopbackAddress() {
        InetAddress result = null;
        try {
            // 记录网卡最小索引
            int lowest = Integer.MAX_VALUE;
            // 获取所有网卡
            for (Enumeration<NetworkInterface> nics = NetworkInterface
                    .getNetworkInterfaces(); nics.hasMoreElements();) {
                NetworkInterface ifc = nics.nextElement();
                if (ifc.isUp()) {
                    log.trace("Testing interface: " + ifc.getDisplayName());
                    if (ifc.getIndex() < lowest || result == null) {
                        lowest = ifc.getIndex(); // 记录索引
                    }
                    else if (result != null) {
                        continue;
                    }
 
                    // @formatter:off
                    if (!ignoreInterface(ifc.getDisplayName())) { // 是否是被忽略的网卡
                        for (Enumeration<InetAddress> addrs = ifc
                                .getInetAddresses(); addrs.hasMoreElements();) {
                            InetAddress address = addrs.nextElement();
                            if (address instanceof Inet4Address
                                    && !address.isLoopbackAddress()
                                    && !ignoreAddress(address)) {
                                log.trace("Found non-loopback interface: "
                                        + ifc.getDisplayName());
                                result = address;
                            }
                        }
                    }
                    // @formatter:on
                }
            }
        }
        catch (IOException ex) {
            log.error("Cannot get first non-loopback address", ex);
        }
 
        if (result != null) {
            return result;
        }
 
        try {
            // 如果以上逻辑都没有找到合适的网卡,则使用JDK的InetAddress.getLocalhost()
            return InetAddress.getLocalHost(); 
        }
        catch (UnknownHostException e) {
            log.warn("Unable to retrieve localhost");
        } 
        return null;
    }

通过源码可以看出,该工具类会获取所有网卡,依次进行遍历,取ip地址合理、索引值最小、已经启动且不在忽略列表的网卡的ip地址作为结果。如果仍然没有找到合适的IP, 那么就将InetAddress.getLocalHost()做为最后的fallback方案。

如何避免此问题

A.忽略指定网卡

spring.cloud.inetutils.gnored-interfaces[0]=eth0 # 忽略eth0, 支持正则表达式

通过配置application.properties让应用忽略无效的网卡。

B.配置host

当网查遍历逻辑都没有找到合适ip时会走JDK的InetAddress.getLocalHost()。该方法会返回当前主机的hostname, 然后会根据hostname解析出对应的ip。因此第二种方案就是配置本机的hostname和/etc/hosts文件,直接将本机的主机名映射到有效IP地址。

C.手工指定IP

# 指定此实例的ip
eureka.instance.ip-address=

# 注册时使用ip而不是主机名
eureka.instance.prefer-ip-address=true

D.启动时指定IP

java -jar -Dspring.cloud.inetutils.preferred-networks=192.168.20.123

E.禁用eth0

查看网卡的连接信息

[root@localhost ~]# nmcli con sh
NAME         UUID                                  TYPE            DEVICE 
System eth0  5fb06bd0-0bb0-7ffb-45f1-d6edd65f3e03  802-3-ethernet  eth0   

禁用eth0

[root@localhost ~]# ifdown eth0Device 'eth0' successfully disconnected.

启用eth0

[root@localhost ~]# ifup eth0
标签: Eureka 多网卡

本文转载自: https://blog.csdn.net/qq_28165595/article/details/128945114
版权归原作者 爱琴孩 所有, 如有侵权,请联系我们删除。

“微服务注册到Eureka之后调用不了”的评论:

还没有评论