You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by zh...@apache.org on 2020/07/16 02:21:53 UTC

[shardingsphere-elasticjob] branch master updated: Consider about improvement of get IP address inaccurate (#1039) (#1069)

This is an automated email from the ASF dual-hosted git repository.

zhangliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere-elasticjob.git


The following commit(s) were added to refs/heads/master by this push:
     new 4635a5d  Consider about improvement of get IP address inaccurate (#1039) (#1069)
4635a5d is described below

commit 4635a5dda4bca7f6eec6c145316f8afbbf99a545
Author: Tboy <gu...@immomo.com>
AuthorDate: Thu Jul 16 10:21:47 2020 +0800

    Consider about improvement of get IP address inaccurate (#1039) (#1069)
---
 .../elasticjob/infra/env/HostException.java        |   4 +
 .../elasticjob/infra/env/IpUtils.java              | 104 ++++++++++++++++-----
 2 files changed, 85 insertions(+), 23 deletions(-)

diff --git a/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/env/HostException.java b/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/env/HostException.java
index 5737135..785318b 100644
--- a/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/env/HostException.java
+++ b/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/env/HostException.java
@@ -29,4 +29,8 @@ public final class HostException extends RuntimeException {
     public HostException(final IOException cause) {
         super(cause);
     }
+    
+    public HostException(final String message) {
+        super(message);
+    }
 }
diff --git a/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/env/IpUtils.java b/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/env/IpUtils.java
index a104ef5..f27a7f6 100644
--- a/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/env/IpUtils.java
+++ b/elasticjob-infra/elasticjob-infra-common/src/main/java/org/apache/shardingsphere/elasticjob/infra/env/IpUtils.java
@@ -20,11 +20,16 @@ package org.apache.shardingsphere.elasticjob.infra.env;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 
+import java.io.IOException;
 import java.net.InetAddress;
 import java.net.NetworkInterface;
 import java.net.SocketException;
 import java.net.UnknownHostException;
+import java.net.Inet6Address;
 import java.util.Enumeration;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
 
 /**
  * IP address utility.
@@ -34,6 +39,8 @@ public final class IpUtils {
     
     public static final String IP_REGEX = "((\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)){3})";
     
+    private static final String PREFERRED_NETWORK_INTERFACE = "elasticjob.preferred.network.interface";
+    
     private static volatile String cachedIpAddress;
     
     /**
@@ -45,42 +52,93 @@ public final class IpUtils {
         if (null != cachedIpAddress) {
             return cachedIpAddress;
         }
-        Enumeration<NetworkInterface> netInterfaces;
+        NetworkInterface networkInterface = findNetworkInterface();
+        if (null != networkInterface) {
+            Enumeration<InetAddress> ipAddresses = networkInterface.getInetAddresses();
+            while (ipAddresses.hasMoreElements()) {
+                InetAddress ipAddress = ipAddresses.nextElement();
+                if (isValidAddress(ipAddress)) {
+                    cachedIpAddress = ipAddress.getHostAddress();
+                    return cachedIpAddress;
+                }
+            }
+        }
+        throw new HostException("ip is null");
+    }
+    
+    private static NetworkInterface findNetworkInterface() {
+        Enumeration<NetworkInterface> interfaces;
         try {
-            netInterfaces = NetworkInterface.getNetworkInterfaces();
+            interfaces = NetworkInterface.getNetworkInterfaces();
         } catch (final SocketException ex) {
             throw new HostException(ex);
         }
-        String localIpAddress = null;
-        while (netInterfaces.hasMoreElements()) {
-            NetworkInterface netInterface = netInterfaces.nextElement();
-            Enumeration<InetAddress> ipAddresses = netInterface.getInetAddresses();
-            while (ipAddresses.hasMoreElements()) {
-                InetAddress ipAddress = ipAddresses.nextElement();
-                if (isPublicIpAddress(ipAddress)) {
-                    String publicIpAddress = ipAddress.getHostAddress();
-                    cachedIpAddress = publicIpAddress;
-                    return publicIpAddress;
-                }
-                if (isLocalIpAddress(ipAddress)) {
-                    localIpAddress = ipAddress.getHostAddress();
+        List<NetworkInterface> validNetworkInterfaces = new LinkedList<>();
+        while (interfaces.hasMoreElements()) {
+            NetworkInterface networkInterface = interfaces.nextElement();
+            if (ignoreNetworkInterface(networkInterface)) {
+                continue;
+            }
+            validNetworkInterfaces.add(networkInterface);
+        }
+        NetworkInterface result = null;
+        for (NetworkInterface each : validNetworkInterfaces) {
+            if (isPreferredNetworkInterface(each)) {
+                result = each;
+                break;
+            }
+        }
+        if (null == result) {
+            result = getFirstNetworkInterface(validNetworkInterfaces);
+        }
+        return result;
+    }
+    
+    private static NetworkInterface getFirstNetworkInterface(final List<NetworkInterface> validNetworkInterfaces) {
+        NetworkInterface result = null;
+        for (NetworkInterface each : validNetworkInterfaces) {
+            Enumeration<InetAddress> addresses = each.getInetAddresses();
+            while (addresses.hasMoreElements()) {
+                InetAddress inetAddress = addresses.nextElement();
+                if (isValidAddress(inetAddress)) {
+                    result = each;
+                    break;
                 }
             }
         }
-        cachedIpAddress = localIpAddress;
-        return localIpAddress;
+        if (null == result && !validNetworkInterfaces.isEmpty()) {
+            result = validNetworkInterfaces.get(0);
+        }
+        return result;
     }
     
-    private static boolean isPublicIpAddress(final InetAddress ipAddress) {
-        return !ipAddress.isSiteLocalAddress() && !ipAddress.isLoopbackAddress() && !isV6IpAddress(ipAddress);
+    private static boolean isPreferredNetworkInterface(final NetworkInterface networkInterface) {
+        String preferredNetworkInterface = System.getProperty(PREFERRED_NETWORK_INTERFACE);
+        return Objects.equals(networkInterface.getDisplayName(), preferredNetworkInterface);
     }
     
-    private static boolean isLocalIpAddress(final InetAddress ipAddress) {
-        return ipAddress.isSiteLocalAddress() && !ipAddress.isLoopbackAddress() && !isV6IpAddress(ipAddress);
+    private static boolean ignoreNetworkInterface(final NetworkInterface networkInterface) {
+        try {
+            return null == networkInterface
+                    || networkInterface.isLoopback()
+                    || networkInterface.isVirtual()
+                    || !networkInterface.isUp();
+        } catch (final SocketException ex) {
+            return true;
+        }
+    }
+    
+    private static boolean isValidAddress(final InetAddress inetAddress) {
+        try {
+            return !inetAddress.isLoopbackAddress() && !inetAddress.isAnyLocalAddress()
+                    && !isIp6Address(inetAddress) && inetAddress.isReachable(100);
+        } catch (final IOException ex) {
+            return false;
+        }
     }
     
-    private static boolean isV6IpAddress(final InetAddress ipAddress) {
-        return ipAddress.getHostAddress().contains(":");
+    private static boolean isIp6Address(final InetAddress ipAddress) {
+        return ipAddress instanceof Inet6Address;
     }
     
     /**