diff --git a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java index 1ec99c1b0382c..3e63e42c13bb8 100644 --- a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java +++ b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java @@ -305,6 +305,9 @@ public class TcpDiscoverySpi extends IgniteSpiAdapter implements IgniteDiscovery /** Ssl message pattern for StreamCorruptedException. */ private static Pattern sslMsgPattern = Pattern.compile("invalid stream header: 150\\d0\\d00"); + /** Number of resolved IP finder addresses that triggers a warning about potentially slow node join. */ + static final int ADDRS_WARN_THRESHOLD = 20; + /** Local address. */ protected String locAddr; @@ -1964,6 +1967,13 @@ protected Collection resolvedAddresses() throws IgniteSpiExce } } + if (res.size() > ADDRS_WARN_THRESHOLD) + LT.warn(log, "Long list of addresses resolved from IP finder: connecting to an unavailable address " + + "usually blocks until socket timeout instead of failing fast (on Windows OS this may look like " + + "the node hangs for a while), so every unreachable address in the list slows down node join or " + + "reconnection. Make sure that all addresses are correct and reachable, consider reducing the " + + "address list or increasing 'joinTimeout' to bound the wait [addrsCnt=" + res.size() + "]"); + if (!res.isEmpty() && !skipAddrsRandomization) Collections.shuffle(res); diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoveryLongAddressListWarnSelfTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoveryLongAddressListWarnSelfTest.java new file mode 100644 index 0000000000000..90b25e71502b8 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoveryLongAddressListWarnSelfTest.java @@ -0,0 +1,97 @@ +/* + * 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.ignite.spi.discovery.tcp; + +import java.util.ArrayList; +import java.util.List; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder; +import org.apache.ignite.testframework.GridStringLogger; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; +import org.junit.Test; + +/** + * Tests that a warning is printed when the IP finder has a long list of addresses (see IGNITE-1025). + */ +public class TcpDiscoveryLongAddressListWarnSelfTest extends GridCommonAbstractTest { + /** Base port for unavailable addresses. */ + private static final int UNAVAILABLE_PORT = 49_152; + + /** */ + private GridStringLogger strLog; + + /** */ + private int addrCnt; + + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { + IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName); + + List addrs = new ArrayList<>(addrCnt); + + for (int i = 0; i < addrCnt; i++) + addrs.add("127.0.0.1:" + (UNAVAILABLE_PORT + i)); + + TcpDiscoverySpi spi = new TcpDiscoverySpi() + .setIpFinder(new TcpDiscoveryVmIpFinder(true).setAddresses(addrs)) + .setJoinTimeout(1_000); + + cfg.setDiscoverySpi(spi); + cfg.setGridLogger(strLog); + + return cfg; + } + + /** + * @throws Exception If failed. + */ + @Test + public void testWarnOnLongAddressList() throws Exception { + strLog = new GridStringLogger(); + + addrCnt = TcpDiscoverySpi.ADDRS_WARN_THRESHOLD + 1; + + startGrid(0); + + String log = strLog.toString(); + + assertTrue("Warning must be printed to log: " + log, + log.contains("Long list of addresses resolved from IP finder")); + + stopAllGrids(); + } + + /** + * @throws Exception If failed. + */ + @Test + public void testNoWarnOnShortAddressList() throws Exception { + strLog = new GridStringLogger(); + + addrCnt = 3; + + startGrid(0); + + String log = strLog.toString(); + + assertFalse("Warning must not be printed to log: " + log, + log.contains("Long list of addresses resolved from IP finder")); + + stopAllGrids(); + } +}