You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flink.apache.org by tr...@apache.org on 2018/10/18 09:35:02 UTC
[flink] branch master updated: [FLINK-10580] Harden
BootstrapTool#startActorSystem
This is an automated email from the ASF dual-hosted git repository.
trohrmann pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flink.git
The following commit(s) were added to refs/heads/master by this push:
new 7dbe4bb [FLINK-10580] Harden BootstrapTool#startActorSystem
7dbe4bb is described below
commit 7dbe4bb194f79cd996b46c36037b512e93b1ef07
Author: Till Rohrmann <tr...@apache.org>
AuthorDate: Wed Oct 17 13:35:51 2018 +0200
[FLINK-10580] Harden BootstrapTool#startActorSystem
Instead of opening a socket to check whether a given port is free we simply start an
ActorSystem with it an check whether it can bind to this port. This also solves the problem
that a 0 port get resolved to a specific port which might get taken between closing the
test socket and starting the ActorSystem.
---
.../runtime/clusterframework/BootstrapTools.java | 15 +-----
.../clusterframework/BootstrapToolsTest.java | 57 +++++++++++++++++++++-
2 files changed, 57 insertions(+), 15 deletions(-)
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/BootstrapTools.java b/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/BootstrapTools.java
index d95034d..3a2d2c5 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/BootstrapTools.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/BootstrapTools.java
@@ -55,7 +55,6 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.BindException;
-import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -157,19 +156,7 @@ public class BootstrapTools {
}
while (portsIterator.hasNext()) {
- // first, we check if the port is available by opening a socket
- // if the actor system fails to start on the port, we try further
- ServerSocket availableSocket = NetUtils.createSocketFromPorts(portsIterator, ServerSocket::new);
-
- int port;
- if (availableSocket == null) {
- throw new BindException("Unable to allocate further port in port range: " + portRangeDefinition);
- } else {
- port = availableSocket.getLocalPort();
- try {
- availableSocket.close();
- } catch (IOException ignored) {}
- }
+ final int port = portsIterator.next();
try {
return startActorSystem(
diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/clusterframework/BootstrapToolsTest.java b/flink-runtime/src/test/java/org/apache/flink/runtime/clusterframework/BootstrapToolsTest.java
index d1f32cf..c01f1aa 100644
--- a/flink-runtime/src/test/java/org/apache/flink/runtime/clusterframework/BootstrapToolsTest.java
+++ b/flink-runtime/src/test/java/org/apache/flink/runtime/clusterframework/BootstrapToolsTest.java
@@ -21,10 +21,26 @@ package org.apache.flink.runtime.clusterframework;
import org.apache.flink.configuration.ConfigConstants;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.configuration.CoreOptions;
+import org.apache.flink.runtime.akka.AkkaUtils;
+import org.apache.flink.runtime.concurrent.FutureUtils;
+import org.apache.flink.util.ExecutorUtils;
+import org.apache.flink.util.TestLogger;
+import org.apache.flink.util.function.CheckedSupplier;
+import akka.actor.ActorSystem;
import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -33,7 +49,9 @@ import static org.junit.Assert.assertNull;
/**
* Tests for {@link BootstrapToolsTest}.
*/
-public class BootstrapToolsTest {
+public class BootstrapToolsTest extends TestLogger {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BootstrapToolsTest.class);
@Test
public void testSubstituteConfigKey() {
@@ -305,4 +323,41 @@ public class BootstrapToolsTest {
BootstrapTools.updateTmpDirectoriesInConfiguration(config, null);
assertEquals(config.getString(CoreOptions.TMP_DIRS), CoreOptions.TMP_DIRS.defaultValue());
}
+
+ /**
+ * Tests that we can concurrently create two {@link ActorSystem} without port conflicts.
+ * This effectively tests that we don't open a socket to check for a ports availability.
+ * See FLINK-10580 for more details.
+ */
+ @Test
+ public void testConcurrentActorSystemCreation() throws Exception {
+ final int concurrentCreations = 10;
+ final ExecutorService executorService = Executors.newFixedThreadPool(concurrentCreations);
+ final CyclicBarrier cyclicBarrier = new CyclicBarrier(concurrentCreations);
+
+ try {
+ final List<CompletableFuture<Void>> actorSystemFutures = IntStream.range(0, concurrentCreations)
+ .mapToObj(
+ ignored ->
+ CompletableFuture.supplyAsync(
+ CheckedSupplier.unchecked(() -> {
+ cyclicBarrier.await();
+
+ return BootstrapTools.startActorSystem(
+ new Configuration(),
+ "localhost",
+ "0",
+ LOG);
+ })))
+ .map(
+ // terminate ActorSystems
+ actorSystemFuture ->
+ actorSystemFuture.thenCompose(AkkaUtils::terminateActorSystem)
+ ).collect(Collectors.toList());
+
+ FutureUtils.completeAll(actorSystemFutures).get();
+ } finally {
+ ExecutorUtils.gracefulShutdown(10000L, TimeUnit.MILLISECONDS, executorService);
+ }
+ }
}