The microservice cannot be called after it is registered to Eureka

foreword

Some time ago, a colleague reported that an order service in the development joint debugging environment could not be accessed. Clicking on the service on the Eureka page was also a link rejection. It was strange that the ip connected to the access was an unfamiliar IP, not the ip of the order service deployment server. Later, I checked After checking the server network card information, it was found that a new network card was mounted on the server.

 The service registered to the Eureka server is the address of 172.30.32.16. At that time, this ip was actually inaccessible, so the service registered with Eureka successfully, but the service could not be called.

Selection of Eureka service registration IP in multi-network card environment

For the above problem, how do we generally solve it? This requires looking at the source code of Eureka. The source code of Eureka Client is under the eureka-client module. The InstanceInfo class under the com.netflix.appinfo package encapsulates the local information, including the IP address. In the Spring Cloud environment, Eureka Client does not implement the logic of detecting the local IP by itself, but hand it over to the findFirstNonLoopbackAddress() method of Spring's InetUtils tool class:

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;
    }

It can be seen from the source code that this tool class will obtain all network cards, traverse them in turn, and take the IP address of the network card with a reasonable ip address, the smallest index value, which has been started and is not in the ignore list as the result. If you still can't find a suitable IP, then use InetAddress.getLocalHost() as the last fallback solution.

how to avoid this problem

A. Ignore the specified network card

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

Let the application ignore invalid network cards by configuring application.properties.

B. Configure the host

When the network search traversal logic does not find a suitable ip, it will use JDK's InetAddress.getLocalHost(). This method will return the hostname of the current host, and then resolve the corresponding ip according to the hostname. Therefore, the second solution is to configure the hostname and /etc/hosts files of the local machine, and directly map the host name of the local machine to a valid IP address.

C. Manually specify IP

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

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

D. Specify IP at startup

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

E. Disable eth0

View the connection information of the network card

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

disable eth0

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

enable eth0

[root@localhost ~]# ifup eth0

Guess you like

Origin blog.csdn.net/qq_28165595/article/details/128945114