From b4dfa6457ee04d580178e763e34bbfc314f88280 Mon Sep 17 00:00:00 2001 From: wangkaish <8738115@qq.com> Date: Wed, 27 Jan 2021 14:33:59 +0800 Subject: [PATCH] [ISSUE #2633] Cache NetworkInterfaces to reduce the time taken to access network card information --- .../apache/rocketmq/client/ClientConfig.java | 4 +- .../apache/rocketmq/common/BrokerConfig.java | 5 +- .../org/apache/rocketmq/common/MixAll.java | 57 +++++++++++++++- .../rocketmq/common/NetworkInterfaceUtil.java | 65 +++++++++++++++++++ .../org/apache/rocketmq/common/UtilAll.java | 2 +- .../rocketmq/common/RemotingUtilTest.java | 3 +- .../remoting/common/RemotingUtil.java | 10 +++ 7 files changed, 136 insertions(+), 10 deletions(-) create mode 100644 common/src/main/java/org/apache/rocketmq/common/NetworkInterfaceUtil.java diff --git a/client/src/main/java/org/apache/rocketmq/client/ClientConfig.java b/client/src/main/java/org/apache/rocketmq/client/ClientConfig.java index d0ae5e1b831..1f9996b553c 100644 --- a/client/src/main/java/org/apache/rocketmq/client/ClientConfig.java +++ b/client/src/main/java/org/apache/rocketmq/client/ClientConfig.java @@ -21,11 +21,11 @@ import java.util.Iterator; import java.util.Set; import org.apache.commons.lang3.StringUtils; +import org.apache.rocketmq.common.MixAll; import org.apache.rocketmq.common.UtilAll; import org.apache.rocketmq.common.message.MessageQueue; import org.apache.rocketmq.common.protocol.NamespaceUtil; import org.apache.rocketmq.common.utils.NameServerAddressUtils; -import org.apache.rocketmq.remoting.common.RemotingUtil; import org.apache.rocketmq.remoting.netty.TlsSystemConfig; import org.apache.rocketmq.remoting.protocol.LanguageCode; @@ -35,7 +35,7 @@ public class ClientConfig { public static final String SEND_MESSAGE_WITH_VIP_CHANNEL_PROPERTY = "com.rocketmq.sendMessageWithVIPChannel"; private String namesrvAddr = NameServerAddressUtils.getNameServerAddresses(); - private String clientIP = RemotingUtil.getLocalAddress(); + private String clientIP = MixAll.getLocalAddress(); private String instanceName = System.getProperty("rocketmq.client.name", "DEFAULT"); private int clientCallbackExecutorThreads = Runtime.getRuntime().availableProcessors(); protected String namespace; diff --git a/common/src/main/java/org/apache/rocketmq/common/BrokerConfig.java b/common/src/main/java/org/apache/rocketmq/common/BrokerConfig.java index d80b3d2169b..ebe382b6b10 100644 --- a/common/src/main/java/org/apache/rocketmq/common/BrokerConfig.java +++ b/common/src/main/java/org/apache/rocketmq/common/BrokerConfig.java @@ -24,7 +24,6 @@ import org.apache.rocketmq.common.topic.TopicValidator; import org.apache.rocketmq.logging.InternalLogger; import org.apache.rocketmq.logging.InternalLoggerFactory; -import org.apache.rocketmq.remoting.common.RemotingUtil; public class BrokerConfig { private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.COMMON_LOGGER_NAME); @@ -33,8 +32,8 @@ public class BrokerConfig { @ImportantField private String namesrvAddr = System.getProperty(MixAll.NAMESRV_ADDR_PROPERTY, System.getenv(MixAll.NAMESRV_ADDR_ENV)); @ImportantField - private String brokerIP1 = RemotingUtil.getLocalAddress(); - private String brokerIP2 = RemotingUtil.getLocalAddress(); + private String brokerIP1 = MixAll.getLocalAddress(); + private String brokerIP2 = MixAll.getLocalAddress(); @ImportantField private String brokerName = localHostName(); @ImportantField diff --git a/common/src/main/java/org/apache/rocketmq/common/MixAll.java b/common/src/main/java/org/apache/rocketmq/common/MixAll.java index 9d95ecb5ea4..bb576092b1f 100644 --- a/common/src/main/java/org/apache/rocketmq/common/MixAll.java +++ b/common/src/main/java/org/apache/rocketmq/common/MixAll.java @@ -358,7 +358,7 @@ public static boolean isPropertiesEqual(final Properties p1, final Properties p2 public static List getLocalInetAddress() { List inetAddressList = new ArrayList(); try { - Enumeration enumeration = NetworkInterface.getNetworkInterfaces(); + Enumeration enumeration = NetworkInterfaceUtil.getNetworkInterfaces(); while (enumeration.hasMoreElements()) { NetworkInterface networkInterface = enumeration.nextElement(); Enumeration addrs = networkInterface.getInetAddresses(); @@ -392,7 +392,7 @@ private static String localhost() { //Reverse logic comparing to RemotingUtil method, consider refactor in RocketMQ 5.0 public static String getLocalhostByNetworkInterface() throws SocketException { List candidatesHost = new ArrayList(); - Enumeration enumeration = NetworkInterface.getNetworkInterfaces(); + Enumeration enumeration = NetworkInterfaceUtil.getNetworkInterfaces(); while (enumeration.hasMoreElements()) { NetworkInterface networkInterface = enumeration.nextElement(); @@ -443,4 +443,57 @@ public static String humanReadableByteCount(long bytes, boolean si) { return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); } + public static String getLocalAddress() { + try { + // Traversal Network interface to get the first non-loopback and non-private address + Enumeration enumeration = NetworkInterfaceUtil.getNetworkInterfaces(); + ArrayList ipv4Result = new ArrayList(); + ArrayList ipv6Result = new ArrayList(); + while (enumeration.hasMoreElements()) { + final NetworkInterface networkInterface = enumeration.nextElement(); + final Enumeration en = networkInterface.getInetAddresses(); + while (en.hasMoreElements()) { + final InetAddress address = en.nextElement(); + if (!address.isLoopbackAddress()) { + if (address instanceof Inet6Address) { + ipv6Result.add(normalizeHostAddress(address)); + } else { + ipv4Result.add(normalizeHostAddress(address)); + } + } + } + } + + // prefer ipv4 + if (!ipv4Result.isEmpty()) { + for (String ip : ipv4Result) { + if (ip.startsWith("127.0") || ip.startsWith("192.168")) { + continue; + } + + return ip; + } + + return ipv4Result.get(ipv4Result.size() - 1); + } else if (!ipv6Result.isEmpty()) { + return ipv6Result.get(0); + } + //If failed to find,fall back to localhost + final InetAddress localHost = InetAddress.getLocalHost(); + return normalizeHostAddress(localHost); + } catch (Exception e) { + log.error("Failed to obtain local address", e); + } + + return null; + } + + public static String normalizeHostAddress(final InetAddress localHost) { + if (localHost instanceof Inet6Address) { + return "[" + localHost.getHostAddress() + "]"; + } else { + return localHost.getHostAddress(); + } + } + } diff --git a/common/src/main/java/org/apache/rocketmq/common/NetworkInterfaceUtil.java b/common/src/main/java/org/apache/rocketmq/common/NetworkInterfaceUtil.java new file mode 100644 index 00000000000..685d314b589 --- /dev/null +++ b/common/src/main/java/org/apache/rocketmq/common/NetworkInterfaceUtil.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.rocketmq.common; + +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; + +public class NetworkInterfaceUtil { + + private static final List INTERFACES = new ArrayList<>(); + private static final Throwable THROWABLE; + + static { + Throwable exception = null; + try { + Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces(); + for (; networkInterfaces.hasMoreElements(); ) { + INTERFACES.add(networkInterfaces.nextElement()); + } + } catch (Throwable e) { + exception = e; + } + THROWABLE = exception; + } + + public static Enumeration getNetworkInterfaces() throws SocketException { + if (THROWABLE != null) { + SocketException socketException = new SocketException("Get network interfaces failed"); + socketException.initCause(THROWABLE); + throw socketException; + } else { + Iterator iterator = INTERFACES.iterator(); + return new Enumeration() { + @Override + public boolean hasMoreElements() { + return iterator.hasNext(); + } + + @Override + public NetworkInterface nextElement() { + return iterator.next(); + } + }; + } + } + +} diff --git a/common/src/main/java/org/apache/rocketmq/common/UtilAll.java b/common/src/main/java/org/apache/rocketmq/common/UtilAll.java index aa6920817f1..2c4e8300fb4 100644 --- a/common/src/main/java/org/apache/rocketmq/common/UtilAll.java +++ b/common/src/main/java/org/apache/rocketmq/common/UtilAll.java @@ -505,7 +505,7 @@ public static String ipToIPv6Str(byte[] ip) { public static byte[] getIP() { try { - Enumeration allNetInterfaces = NetworkInterface.getNetworkInterfaces(); + Enumeration allNetInterfaces = NetworkInterfaceUtil.getNetworkInterfaces(); InetAddress ip = null; byte[] internalIP = null; while (allNetInterfaces.hasMoreElements()) { diff --git a/common/src/test/java/org/apache/rocketmq/common/RemotingUtilTest.java b/common/src/test/java/org/apache/rocketmq/common/RemotingUtilTest.java index 586689637b3..882415755e8 100644 --- a/common/src/test/java/org/apache/rocketmq/common/RemotingUtilTest.java +++ b/common/src/test/java/org/apache/rocketmq/common/RemotingUtilTest.java @@ -16,7 +16,6 @@ */ package org.apache.rocketmq.common; -import org.apache.rocketmq.remoting.common.RemotingUtil; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -24,7 +23,7 @@ public class RemotingUtilTest { @Test public void testGetLocalAddress() throws Exception { - String localAddress = RemotingUtil.getLocalAddress(); + String localAddress = MixAll.getLocalAddress(); assertThat(localAddress).isNotNull(); assertThat(localAddress.length()).isGreaterThan(0); } diff --git a/remoting/src/main/java/org/apache/rocketmq/remoting/common/RemotingUtil.java b/remoting/src/main/java/org/apache/rocketmq/remoting/common/RemotingUtil.java index a16940e561c..f9340040789 100644 --- a/remoting/src/main/java/org/apache/rocketmq/remoting/common/RemotingUtil.java +++ b/remoting/src/main/java/org/apache/rocketmq/remoting/common/RemotingUtil.java @@ -90,6 +90,11 @@ public static boolean isLinuxPlatform() { return isLinuxPlatform; } + /** + * This method will be removed, use "org.apache.rocketmq.common.MixAll.getLocalAddress" instead. + * @return + */ + @Deprecated public static String getLocalAddress() { try { // Traversal Network interface to get the first non-loopback and non-private address @@ -135,6 +140,11 @@ public static String getLocalAddress() { return null; } + /** + * This method will be removed, use "org.apache.rocketmq.common.MixAll.normalizeHostAddress" instead. + * @return + */ + @Deprecated public static String normalizeHostAddress(final InetAddress localHost) { if (localHost instanceof Inet6Address) { return "[" + localHost.getHostAddress() + "]";