From cbda95d01408848f095f08e6b08426c44ca98614 Mon Sep 17 00:00:00 2001 From: onewe Date: Mon, 20 Jun 2022 10:23:59 +0800 Subject: [PATCH] [ISSUE #8515] Optimize some code in InetUtils (#8522) * [ISSUE #8515] auto refresh ip address Close #8515 * [ISSUE #8515] add the unit test Close #8515 * [ISSUE #8515] clean system variable after unit test done Close #8515 * [ISSUE #8515] add tearDown method for the unit test - reformat by nacos-style * [ISSUE #8515] fix ci error * [ISSUE #8515] fix ci error * [ISSUE #8515] fix ci error --- .../com/alibaba/nacos/sys/env/Constants.java | 1 + .../alibaba/nacos/sys/utils/InetUtils.java | 162 ++++++++++++------ .../nacos/sys/utils/InetUtilsTest.java | 35 +++- 3 files changed, 139 insertions(+), 59 deletions(-) diff --git a/sys/src/main/java/com/alibaba/nacos/sys/env/Constants.java b/sys/src/main/java/com/alibaba/nacos/sys/env/Constants.java index 0eda3dd08df..6c42d7faf19 100644 --- a/sys/src/main/java/com/alibaba/nacos/sys/env/Constants.java +++ b/sys/src/main/java/com/alibaba/nacos/sys/env/Constants.java @@ -54,6 +54,7 @@ public interface Constants { String USE_ONLY_SITE_INTERFACES = "nacos.inetutils.use-only-site-local-interfaces"; String PREFERRED_NETWORKS = "nacos.inetutils.preferred-networks"; String IGNORED_INTERFACES = "nacos.inetutils.ignored-interfaces"; + String AUTO_REFRESH_TIME = "nacos.core.inet.auto-refresh"; String IP_ADDRESS = "nacos.inetutils.ip-address"; String PREFER_HOSTNAME_OVER_IP = "nacos.inetutils.prefer-hostname-over-ip"; String SYSTEM_PREFER_HOSTNAME_OVER_IP = "nacos.preferHostnameOverIp"; diff --git a/sys/src/main/java/com/alibaba/nacos/sys/utils/InetUtils.java b/sys/src/main/java/com/alibaba/nacos/sys/utils/InetUtils.java index b9f648cc5bf..d796528bd51 100644 --- a/sys/src/main/java/com/alibaba/nacos/sys/utils/InetUtils.java +++ b/sys/src/main/java/com/alibaba/nacos/sys/utils/InetUtils.java @@ -16,6 +16,8 @@ package com.alibaba.nacos.sys.utils; +import com.alibaba.nacos.common.executor.ExecutorFactory; +import com.alibaba.nacos.common.executor.NameThreadFactory; import com.alibaba.nacos.common.notify.NotifyCenter; import com.alibaba.nacos.common.notify.SlowEvent; import com.alibaba.nacos.common.utils.InternetAddressUtil; @@ -35,6 +37,8 @@ import java.util.Enumeration; import java.util.List; import java.util.Objects; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import static com.alibaba.nacos.sys.env.Constants.IP_ADDRESS; import static com.alibaba.nacos.sys.env.Constants.NACOS_SERVER_IP; @@ -51,15 +55,18 @@ public class InetUtils { private static final Logger LOG = LoggerFactory.getLogger(InetUtils.class); - private static String selfIP; + private static final List PREFERRED_NETWORKS = new ArrayList<>(); - private static boolean useOnlySiteLocalInterface = false; + private static final List IGNORED_INTERFACES = new ArrayList<>(); - private static boolean preferHostnameOverIP = false; + private static final ScheduledExecutorService INET_AUTO_REFRESH_EXECUTOR = ExecutorFactory.Managed.newSingleScheduledExecutorService( + InetUtils.class.getCanonicalName(), new NameThreadFactory("com.alibaba.inet.ip.auto-refresh")); - private static final List PREFERRED_NETWORKS = new ArrayList(); + private static volatile String selfIP; - private static final List IGNORED_INTERFACES = new ArrayList(); + private static boolean useOnlySiteLocalInterface = false; + + private static boolean preferHostnameOverIP = false; static { NotifyCenter.registerToSharePublisher(IPChangeEvent.class); @@ -72,60 +79,100 @@ public class InetUtils { List interfaces = EnvUtil.getPropertyList(Constants.IGNORED_INTERFACES); IGNORED_INTERFACES.addAll(interfaces); - final long delayMs = Long.getLong("nacos.core.inet.auto-refresh", 30_000L); + refreshIp(); - Runnable ipAutoRefresh = () -> { - String nacosIP = System.getProperty(NACOS_SERVER_IP); - if (StringUtils.isBlank(nacosIP)) { - nacosIP = EnvUtil.getProperty(IP_ADDRESS); - } - if (!StringUtils.isBlank(nacosIP)) { - if (!(InternetAddressUtil.isIP(nacosIP) || InternetAddressUtil.isDomain(nacosIP))) { - throw new RuntimeException("nacos address " + nacosIP + " is not ip"); - } - } - String tmpSelfIP = nacosIP; - if (StringUtils.isBlank(tmpSelfIP)) { - preferHostnameOverIP = Boolean.getBoolean(SYSTEM_PREFER_HOSTNAME_OVER_IP); - - if (!preferHostnameOverIP) { - preferHostnameOverIP = Boolean.parseBoolean(EnvUtil.getProperty(PREFER_HOSTNAME_OVER_IP)); - } - - if (preferHostnameOverIP) { - InetAddress inetAddress; - try { - inetAddress = InetAddress.getLocalHost(); - if (inetAddress.getHostName().equals(inetAddress.getCanonicalHostName())) { - tmpSelfIP = inetAddress.getHostName(); - } else { - tmpSelfIP = inetAddress.getCanonicalHostName(); - } - } catch (UnknownHostException ignore) { - LOG.warn("Unable to retrieve localhost"); - } - } else { - tmpSelfIP = Objects.requireNonNull(findFirstNonLoopbackAddress()).getHostAddress(); - } + final long delayMs = Long.getLong(Constants.AUTO_REFRESH_TIME, 30_000L); + + INET_AUTO_REFRESH_EXECUTOR.scheduleAtFixedRate(() -> { + try { + InetUtils.refreshIp(); + } catch (Exception e) { + LOG.error("refresh ip error", e); } - if (InternetAddressUtil.PREFER_IPV6_ADDRESSES && !tmpSelfIP.startsWith(InternetAddressUtil.IPV6_START_MARK) && !tmpSelfIP - .endsWith(InternetAddressUtil.IPV6_END_MARK)) { - tmpSelfIP = InternetAddressUtil.IPV6_START_MARK + tmpSelfIP + InternetAddressUtil.IPV6_END_MARK; - if (StringUtils.contains(tmpSelfIP, InternetAddressUtil.PERCENT_SIGN_IN_IPV6)) { - tmpSelfIP = tmpSelfIP.substring(0, tmpSelfIP.indexOf(InternetAddressUtil.PERCENT_SIGN_IN_IPV6)) - + InternetAddressUtil.IPV6_END_MARK; - } + }, delayMs, delayMs, TimeUnit.MILLISECONDS); + } + + /** + * refresh ip address. + */ + private static void refreshIp() { + + String tmpSelfIp = getNacosIp(); + + if (StringUtils.isBlank(tmpSelfIp)) { + tmpSelfIp = getPreferHostnameOverIP(); + } + + if (StringUtils.isBlank(tmpSelfIp)) { + tmpSelfIp = Objects.requireNonNull(findFirstNonLoopbackAddress()).getHostAddress(); + } + + if (InternetAddressUtil.PREFER_IPV6_ADDRESSES && !tmpSelfIp.startsWith(InternetAddressUtil.IPV6_START_MARK) + && !tmpSelfIp.endsWith(InternetAddressUtil.IPV6_END_MARK)) { + tmpSelfIp = InternetAddressUtil.IPV6_START_MARK + tmpSelfIp + InternetAddressUtil.IPV6_END_MARK; + if (StringUtils.contains(tmpSelfIp, InternetAddressUtil.PERCENT_SIGN_IN_IPV6)) { + tmpSelfIp = tmpSelfIp.substring(0, tmpSelfIp.indexOf(InternetAddressUtil.PERCENT_SIGN_IN_IPV6)) + + InternetAddressUtil.IPV6_END_MARK; } - if (!Objects.equals(selfIP, tmpSelfIP) && Objects.nonNull(selfIP)) { - IPChangeEvent event = new IPChangeEvent(); - event.setOldIP(selfIP); - event.setNewIP(tmpSelfIP); - NotifyCenter.publishEvent(event); + } + if (!Objects.equals(selfIP, tmpSelfIp) && Objects.nonNull(selfIP)) { + IPChangeEvent event = new IPChangeEvent(); + event.setOldIP(selfIP); + event.setNewIP(tmpSelfIp); + NotifyCenter.publishEvent(event); + } + selfIP = tmpSelfIp; + } + + /** + * Get ip address from environment + * System property nacos.server.ip + * Spring property nacos.inetutils.ip-address. + * + * @return ip address + */ + private static String getNacosIp() { + String nacosIp = System.getProperty(NACOS_SERVER_IP); + if (StringUtils.isBlank(nacosIp)) { + nacosIp = EnvUtil.getProperty(IP_ADDRESS); + } + if (!StringUtils.isBlank(nacosIp)) { + if (!(InternetAddressUtil.isIP(nacosIp) || InternetAddressUtil.isDomain(nacosIp))) { + throw new RuntimeException("nacos address " + nacosIp + " is not ip"); } - selfIP = tmpSelfIP; - }; + } + + return nacosIp; + } + + /** + * Get ip address. + * + * @return ip address + */ + private static String getPreferHostnameOverIP() { + preferHostnameOverIP = Boolean.getBoolean(SYSTEM_PREFER_HOSTNAME_OVER_IP); + + if (!preferHostnameOverIP) { + preferHostnameOverIP = Boolean.parseBoolean(EnvUtil.getProperty(PREFER_HOSTNAME_OVER_IP)); + } - ipAutoRefresh.run(); + if (!preferHostnameOverIP) { + return null; + } + String preferHostnameOverIp = null; + InetAddress inetAddress; + try { + inetAddress = InetAddress.getLocalHost(); + if (inetAddress.getHostName().equals(inetAddress.getCanonicalHostName())) { + preferHostnameOverIp = inetAddress.getHostName(); + } else { + preferHostnameOverIp = inetAddress.getCanonicalHostName(); + } + } catch (UnknownHostException ignore) { + LOG.warn("Unable to retrieve localhost"); + } + return preferHostnameOverIp; } public static String getSelfIP() { @@ -156,8 +203,9 @@ public static InetAddress findFirstNonLoopbackAddress() { if (!ignoreInterface(ifc.getDisplayName())) { for (Enumeration addrs = ifc.getInetAddresses(); addrs.hasMoreElements(); ) { InetAddress address = addrs.nextElement(); - boolean isLegalIpVersion = InternetAddressUtil.PREFER_IPV6_ADDRESSES ? address instanceof Inet6Address - : address instanceof Inet4Address; + boolean isLegalIpVersion = + InternetAddressUtil.PREFER_IPV6_ADDRESSES ? address instanceof Inet6Address + : address instanceof Inet4Address; if (isLegalIpVersion && !address.isLoopbackAddress() && isPreferredAddress(address)) { LOG.debug("Found non-loopback interface: " + ifc.getDisplayName()); result = address; @@ -177,7 +225,7 @@ public static InetAddress findFirstNonLoopbackAddress() { try { return InetAddress.getLocalHost(); } catch (UnknownHostException e) { - LOG.warn("Unable to retrieve localhost"); + LOG.error("Unable to retrieve localhost", e); } return null; diff --git a/sys/src/test/java/com/alibaba/nacos/sys/utils/InetUtilsTest.java b/sys/src/test/java/com/alibaba/nacos/sys/utils/InetUtilsTest.java index b961d46b86a..2c8ff308a63 100644 --- a/sys/src/test/java/com/alibaba/nacos/sys/utils/InetUtilsTest.java +++ b/sys/src/test/java/com/alibaba/nacos/sys/utils/InetUtilsTest.java @@ -16,14 +16,45 @@ package com.alibaba.nacos.sys.utils; +import com.alibaba.nacos.common.utils.StringUtils; +import com.alibaba.nacos.sys.env.Constants; import com.alibaba.nacos.sys.env.EnvUtil; +import org.junit.After; +import org.junit.Assert; import org.junit.Before; -import org.springframework.core.env.StandardEnvironment; +import org.junit.Test; +import org.springframework.mock.env.MockEnvironment; + +import java.util.concurrent.TimeUnit; + +import static com.alibaba.nacos.sys.env.Constants.NACOS_SERVER_IP; public class InetUtilsTest { @Before public void setUp() { - EnvUtil.setEnvironment(new StandardEnvironment()); + EnvUtil.setEnvironment(new MockEnvironment()); + } + + @Test + public void testRefreshIp() throws InterruptedException { + System.setProperty(NACOS_SERVER_IP, "1.1.1.1"); + System.setProperty(Constants.AUTO_REFRESH_TIME, "100"); + String selfIP = InetUtils.getSelfIP(); + Assert.assertTrue(StringUtils.equalsIgnoreCase(selfIP, "1.1.1.1")); + + System.setProperty(NACOS_SERVER_IP, "1.1.1.2"); + TimeUnit.MILLISECONDS.sleep(500L); + + selfIP = InetUtils.getSelfIP(); + Assert.assertTrue(StringUtils.equalsIgnoreCase(selfIP, "1.1.1.2")); + } + + @After + public void tearDown() { + System.clearProperty(NACOS_SERVER_IP); + System.clearProperty(Constants.AUTO_REFRESH_TIME); + } + } \ No newline at end of file