Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ISSUE #8515] Optimize some code in InetUtils #8522

Merged
merged 7 commits into from
Jun 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,11 @@ public class HttpHealthCheckProcessorTest {

@Before
public void setUp() {
EnvUtil.setEnvironment(new MockEnvironment());
when(switchDomain.getHttpHealthParams()).thenReturn(new SwitchDomain.HttpHealthParams());
when(healthCheckTaskV2.getClient()).thenReturn(ipPortBasedClient);
when(ipPortBasedClient.getInstancePublishInfo(service)).thenReturn(healthCheckInstancePublishInfo);
httpHealthCheckProcessor = new HttpHealthCheckProcessor(healthCheckCommon, switchDomain);
EnvUtil.setEnvironment(new MockEnvironment());
}

@Test
Expand Down
1 change: 1 addition & 0 deletions sys/src/main/java/com/alibaba/nacos/sys/env/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
162 changes: 105 additions & 57 deletions sys/src/main/java/com/alibaba/nacos/sys/utils/InetUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -51,15 +55,18 @@ public class InetUtils {

private static final Logger LOG = LoggerFactory.getLogger(InetUtils.class);

private static String selfIP;
private static final List<String> PREFERRED_NETWORKS = new ArrayList<>();

private static boolean useOnlySiteLocalInterface = false;
private static final List<String> 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<String> PREFERRED_NETWORKS = new ArrayList<String>();
private static volatile String selfIP;

private static final List<String> IGNORED_INTERFACES = new ArrayList<String>();
private static boolean useOnlySiteLocalInterface = false;

private static boolean preferHostnameOverIP = false;

static {
NotifyCenter.registerToSharePublisher(IPChangeEvent.class);
Expand All @@ -72,60 +79,100 @@ public class InetUtils {
List<String> 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() {
Expand Down Expand Up @@ -156,8 +203,9 @@ public static InetAddress findFirstNonLoopbackAddress() {
if (!ignoreInterface(ifc.getDisplayName())) {
for (Enumeration<InetAddress> 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;
onewe marked this conversation as resolved.
Show resolved Hide resolved
if (isLegalIpVersion && !address.isLoopbackAddress() && isPreferredAddress(address)) {
LOG.debug("Found non-loopback interface: " + ifc.getDisplayName());
result = address;
Expand All @@ -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;
Expand Down
35 changes: 33 additions & 2 deletions sys/src/test/java/com/alibaba/nacos/sys/utils/InetUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
onewe marked this conversation as resolved.
Show resolved Hide resolved
System.clearProperty(Constants.AUTO_REFRESH_TIME);
}

}