IGNITE-17414 Fix node is trying to resolve its hostname if IP is configured with IGNITE_LOCAL_HOST (#10169)
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
index 45de839..3c61822 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
@@ -43,6 +43,7 @@
import org.apache.ignite.internal.processors.query.schema.SchemaIndexCachePartitionWorker;
import org.apache.ignite.internal.processors.rest.GridRestCommand;
import org.apache.ignite.internal.util.GridLogThrottle;
+import org.apache.ignite.internal.util.IgniteUtils;
import org.apache.ignite.lang.IgniteExperimental;
import org.apache.ignite.mxbean.MetricsMxBean;
import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
@@ -1012,6 +1013,17 @@
"in configuration", type = String.class)
public static final String IGNITE_OVERRIDE_CONSISTENT_ID = "IGNITE_OVERRIDE_CONSISTENT_ID";
+ /**
+ * System property to ignore reading hostname of the local address.
+ * <p>
+ * If set to {@code true} and {@link #IGNITE_LOCAL_HOST} is defined then
+ * {@link IgniteUtils#resolveLocalAddresses} will not add hostname of local address to the list of node's addresses.
+ * Defaults to {@code true}.
+ */
+ @SystemProperty(value = "Ignores local address's hostname if IGNITE_LOCAL_HOST is defined "
+ + "when resolving local node's addresses", defaults = "true")
+ public static final String IGNITE_IGNORE_LOCAL_HOST_NAME = "IGNITE_IGNORE_LOCAL_HOST_NAME";
+
/** */
@SystemProperty(value = "IO balance period in milliseconds", type = Long.class,
defaults = "" + DFLT_IO_BALANCE_PERIOD)
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
index a29516d..ec87643 100755
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
@@ -140,6 +140,7 @@
import java.util.concurrent.Future;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Condition;
@@ -248,6 +249,7 @@
import org.apache.ignite.internal.util.typedef.X;
import org.apache.ignite.internal.util.typedef.internal.A;
import org.apache.ignite.internal.util.typedef.internal.LT;
+import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.SB;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.internal.util.worker.GridWorker;
@@ -290,6 +292,7 @@
import static java.util.Objects.isNull;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_DISABLE_HOSTNAME_VERIFIER;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_HOME;
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_IGNORE_LOCAL_HOST_NAME;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_LOCAL_HOST;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_MBEAN_APPEND_CLASS_LOADER_ID;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_MBEAN_APPEND_JVM_ID;
@@ -299,6 +302,7 @@
import static org.apache.ignite.IgniteSystemProperties.IGNITE_SSH_USER_NAME;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_SUCCESS_FILE;
import static org.apache.ignite.IgniteSystemProperties.getBoolean;
+import static org.apache.ignite.IgniteSystemProperties.getString;
import static org.apache.ignite.events.EventType.EVTS_ALL;
import static org.apache.ignite.events.EventType.EVTS_ALL_MINUS_METRIC_UPDATE;
import static org.apache.ignite.events.EventType.EVT_NODE_METRICS_UPDATED;
@@ -318,6 +322,9 @@
*/
@SuppressWarnings({"UnusedReturnValue"})
public abstract class IgniteUtils {
+ /** Logger. */
+ private static final Logger log = Logger.getLogger(IgniteUtils.class.getName());
+
/** */
public static final long KB = 1024L;
@@ -2277,12 +2284,20 @@
*/
private static void addresses(InetAddress addr, Collection<String> addrs, Collection<String> hostNames,
boolean allHostNames) {
- String hostName = addr.getHostName();
-
String ipAddr = addr.getHostAddress();
addrs.add(ipAddr);
+ boolean ignoreLocalHostName = getBoolean(IGNITE_IGNORE_LOCAL_HOST_NAME, true);
+
+ String userDefinedLocalHost = getString(IGNITE_LOCAL_HOST);
+
+ // If IGNITE_LOCAL_HOST is defined and IGNITE_IGNORE_LOCAL_HOST_NAME is not false, then ignore local address's hostname
+ if (!F.isEmpty(userDefinedLocalHost) && ignoreLocalHostName)
+ return;
+
+ String hostName = addr.getHostName();
+
if (allHostNames)
hostNames.add(hostName);
else if (!F.isEmpty(hostName) && !addr.isLoopbackAddress())
@@ -9650,23 +9665,65 @@
String hostName = hostNamesIt.hasNext() ? hostNamesIt.next() : null;
if (!F.isEmpty(hostName)) {
- InetSocketAddress inetSockAddr = new InetSocketAddress(hostName, port);
+ InetSocketAddress inetSockAddr = createResolved(hostName, port);
- if (inetSockAddr.isUnresolved() || inetSockAddr.getAddress().isLoopbackAddress())
- inetSockAddr = new InetSocketAddress(addr, port);
+ if (inetSockAddr.isUnresolved() ||
+ (!inetSockAddr.isUnresolved() && inetSockAddr.getAddress().isLoopbackAddress())
+ )
+ inetSockAddr = createResolved(addr, port);
res.add(inetSockAddr);
}
// Always append address because local and remote nodes may have the same hostname
- // therefore remote hostname will be always resolved to local address.
- res.add(new InetSocketAddress(addr, port));
+ // therefore remote hostname will always be resolved to local address.
+ res.add(createResolved(addr, port));
}
return res;
}
/**
+ * Creates a resolved inet socket address, writing the diagnostic information into a log if operation took
+ * a significant amount of time.
+ *
+ * @param addr Host address.
+ * @param port Port value.
+ * @return Resolved address.
+ */
+ private static InetSocketAddress createResolved(String addr, int port) {
+ log.log(Level.FINE, () -> S.toString(
+ "Resolving address",
+ "addr", addr, false,
+ "port", port, false,
+ "thread", Thread.currentThread().getName(), false
+ ));
+
+ long startNanos = System.nanoTime();
+
+ try {
+ return new InetSocketAddress(addr, port);
+ }
+ finally {
+ long endNanos = System.nanoTime();
+
+ long duration = endNanos - startNanos;
+
+ long threshold = U.millisToNanos(200);
+
+ if (duration > threshold) {
+ log.log(Level.FINE, new TimeoutException(), () -> S.toString(
+ "Resolving address took too much time",
+ "duration(ms)", U.nanosToMillis(duration), false,
+ "addr", addr, false,
+ "port", port, false,
+ "thread", Thread.currentThread().getName(), false
+ ));
+ }
+ }
+ }
+
+ /**
* Resolves all not loopback addresses and collect results.
*
* @param addrRslvr Address resolver.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/IgniteUtilsSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/IgniteUtilsSelfTest.java
index 1800077..9fbd2b9 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/util/IgniteUtilsSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/util/IgniteUtilsSelfTest.java
@@ -62,6 +62,7 @@
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteException;
import org.apache.ignite.IgniteInterruptedException;
+import org.apache.ignite.IgniteSystemProperties;
import org.apache.ignite.cluster.ClusterGroup;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.compute.ComputeJob;
@@ -79,6 +80,7 @@
import org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoveryNode;
import org.apache.ignite.testframework.GridTestUtils;
import org.apache.ignite.testframework.http.GridEmbeddedHttpServer;
+import org.apache.ignite.testframework.junits.WithSystemProperty;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.apache.ignite.testframework.junits.common.GridCommonTest;
import org.apache.ignite.thread.IgniteThreadFactory;
@@ -1484,6 +1486,64 @@
}
/**
+ * Tests that local hostname is ignored if {@link IgniteSystemProperties#IGNITE_IGNORE_LOCAL_HOST_NAME} is
+ * set to {@code true}.
+ *
+ * @throws Exception If failed.
+ */
+ @Test
+ @WithSystemProperty(key = IgniteSystemProperties.IGNITE_LOCAL_HOST, value = "example.com")
+ @WithSystemProperty(key = IgniteSystemProperties.IGNITE_IGNORE_LOCAL_HOST_NAME, value = "true")
+ public void testResolveLocalAddressesWithHostNameDefined() throws Exception {
+ testAddressResolveWithLocalHostDefined();
+ }
+
+ /**
+ * Tests that local hostname is not ignored if {@link IgniteSystemProperties#IGNITE_IGNORE_LOCAL_HOST_NAME} is
+ * set to {@code false}.
+ *
+ * @throws Exception If failed.
+ */
+ @Test
+ @WithSystemProperty(key = IgniteSystemProperties.IGNITE_LOCAL_HOST, value = "example.com")
+ @WithSystemProperty(key = IgniteSystemProperties.IGNITE_IGNORE_LOCAL_HOST_NAME, value = "false")
+ public void testResolveLocalAddressesWithHostNameDefinedAndLocalHostNameNotIgnored() throws Exception {
+ testAddressResolveWithLocalHostDefined();
+ }
+
+ /**
+ * Tests {@link IgniteUtils#resolveLocalAddresses(InetAddress)} with different values set to
+ * {@link IgniteSystemProperties#IGNITE_LOCAL_HOST} and {@link IgniteSystemProperties#IGNITE_IGNORE_LOCAL_HOST_NAME}.
+ *
+ * @throws Exception If failed.
+ */
+ private void testAddressResolveWithLocalHostDefined() throws Exception {
+ try {
+ boolean ignoreLocalHostname = IgniteSystemProperties.getBoolean(IgniteSystemProperties.IGNITE_IGNORE_LOCAL_HOST_NAME);
+ String userDefinedHost = IgniteSystemProperties.getString(IgniteSystemProperties.IGNITE_LOCAL_HOST);
+
+ InetSocketAddress inetSocketAddress = new InetSocketAddress(userDefinedHost, 0);
+ InetAddress addr = inetSocketAddress.getAddress();
+ IgniteBiTuple<Collection<String>, Collection<String>> localAddresses = IgniteUtils.resolveLocalAddresses(addr);
+
+ if (ignoreLocalHostname) {
+ // If local hostname is ignored, then no hostname should be resolved.
+ assertTrue(localAddresses.get2().isEmpty());
+ }
+ else {
+ // If local hostname is not ignored, then we should receive example.com.
+ assertFalse(localAddresses.get2().isEmpty());
+ assertEquals("example.com", F.first(localAddresses.get2()));
+ }
+ }
+ finally {
+ // Clear local address cache as we have polluted it with this test.
+ GridTestUtils.setFieldValue(IgniteUtils.class, "cachedLocalAddrAllHostNames", null);
+ GridTestUtils.setFieldValue(IgniteUtils.class, "cachedLocalAddr", null);
+ }
+ }
+
+ /**
* Test enum.
*/
private enum TestEnum {