Don't update nodes list when stepping down as master (#22049)

This commit simplifies the node update logic so that nodes are never removed from the cluster state when the cluster state is not published.
This commit is contained in:
Yannick Welsch 2016-12-09 14:55:48 +01:00 committed by GitHub
parent 2592ff86ce
commit a724f4eb61
2 changed files with 31 additions and 32 deletions

View File

@ -72,6 +72,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.elasticsearch.common.unit.TimeValue.timeValueSeconds; import static org.elasticsearch.common.unit.TimeValue.timeValueSeconds;
@ -207,7 +208,7 @@ public class ZenDiscovery extends AbstractLifecycleComponent implements Discover
joinThreadControl.start(); joinThreadControl.start();
zenPing.start(this); zenPing.start(this);
this.nodeJoinController = new NodeJoinController(clusterService, allocationService, electMaster, discoverySettings, settings); this.nodeJoinController = new NodeJoinController(clusterService, allocationService, electMaster, discoverySettings, settings);
this.nodeRemovalExecutor = new NodeRemovalClusterStateTaskExecutor(allocationService, electMaster, this::rejoin, logger); this.nodeRemovalExecutor = new NodeRemovalClusterStateTaskExecutor(allocationService, electMaster, this::submitRejoin, logger);
} }
@Override @Override
@ -306,18 +307,7 @@ public class ZenDiscovery extends AbstractLifecycleComponent implements Discover
} catch (FailedToCommitClusterStateException t) { } catch (FailedToCommitClusterStateException t) {
// cluster service logs a WARN message // cluster service logs a WARN message
logger.debug("failed to publish cluster state version [{}] (not enough nodes acknowledged, min master nodes [{}])", clusterChangedEvent.state().version(), electMaster.minimumMasterNodes()); logger.debug("failed to publish cluster state version [{}] (not enough nodes acknowledged, min master nodes [{}])", clusterChangedEvent.state().version(), electMaster.minimumMasterNodes());
clusterService.submitStateUpdateTask("zen-disco-failed-to-publish", new ClusterStateUpdateTask(Priority.IMMEDIATE) { submitRejoin("zen-disco-failed-to-publish");
@Override
public ClusterState execute(ClusterState currentState) {
return rejoin(currentState, "failed to publish to min_master_nodes");
}
@Override
public void onFailure(String source, Exception e) {
logger.error((Supplier<?>) () -> new ParameterizedMessage("unexpected failure during [{}]", source), e);
}
});
throw t; throw t;
} }
@ -505,12 +495,27 @@ public class ZenDiscovery extends AbstractLifecycleComponent implements Discover
} }
} }
private void submitRejoin(String source) {
clusterService.submitStateUpdateTask(source, new ClusterStateUpdateTask(Priority.IMMEDIATE) {
@Override
public ClusterState execute(ClusterState currentState) {
return rejoin(currentState, source);
}
@Override
public void onFailure(String source, Exception e) {
logger.error((Supplier<?>) () -> new ParameterizedMessage("unexpected failure during [{}]", source), e);
}
});
}
// visible for testing // visible for testing
static class NodeRemovalClusterStateTaskExecutor implements ClusterStateTaskExecutor<NodeRemovalClusterStateTaskExecutor.Task>, ClusterStateTaskListener { static class NodeRemovalClusterStateTaskExecutor implements ClusterStateTaskExecutor<NodeRemovalClusterStateTaskExecutor.Task>, ClusterStateTaskListener {
private final AllocationService allocationService; private final AllocationService allocationService;
private final ElectMasterService electMasterService; private final ElectMasterService electMasterService;
private final BiFunction<ClusterState, String, ClusterState> rejoin; private final Consumer<String> rejoin;
private final Logger logger; private final Logger logger;
static class Task { static class Task {
@ -540,7 +545,7 @@ public class ZenDiscovery extends AbstractLifecycleComponent implements Discover
NodeRemovalClusterStateTaskExecutor( NodeRemovalClusterStateTaskExecutor(
final AllocationService allocationService, final AllocationService allocationService,
final ElectMasterService electMasterService, final ElectMasterService electMasterService,
final BiFunction<ClusterState, String, ClusterState> rejoin, final Consumer<String> rejoin,
final Logger logger) { final Logger logger) {
this.allocationService = allocationService; this.allocationService = allocationService;
this.electMasterService = electMasterService; this.electMasterService = electMasterService;
@ -570,7 +575,8 @@ public class ZenDiscovery extends AbstractLifecycleComponent implements Discover
final BatchResult.Builder<Task> resultBuilder = BatchResult.<Task>builder().successes(tasks); final BatchResult.Builder<Task> resultBuilder = BatchResult.<Task>builder().successes(tasks);
if (!electMasterService.hasEnoughMasterNodes(remainingNodesClusterState.nodes())) { if (!electMasterService.hasEnoughMasterNodes(remainingNodesClusterState.nodes())) {
return resultBuilder.build(rejoin.apply(remainingNodesClusterState, "not enough master nodes")); rejoin.accept("not enough master nodes");
return resultBuilder.build(currentState);
} else { } else {
return resultBuilder.build(allocationService.deassociateDeadNodes(remainingNodesClusterState, true, describeTasks(tasks))); return resultBuilder.build(allocationService.deassociateDeadNodes(remainingNodesClusterState, true, describeTasks(tasks)));
} }

View File

@ -33,6 +33,7 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
@ -77,17 +78,12 @@ public class NodeRemovalClusterStateTaskExecutorTests extends ESTestCase {
final AllocationService allocationService = mock(AllocationService.class); final AllocationService allocationService = mock(AllocationService.class);
final AtomicBoolean rejoined = new AtomicBoolean(); final AtomicBoolean rejoinCalled = new AtomicBoolean();
final AtomicReference<ClusterState> rejoinedClusterState = new AtomicReference<>(); final Consumer<String> submitRejoin = source -> rejoinCalled.set(true);
final BiFunction<ClusterState, String, ClusterState> rejoin = (cs, r) -> {
rejoined.set(true);
rejoinedClusterState.set(ClusterState.builder(cs).build());
return rejoinedClusterState.get();
};
final AtomicReference<ClusterState> remainingNodesClusterState = new AtomicReference<>(); final AtomicReference<ClusterState> remainingNodesClusterState = new AtomicReference<>();
final ZenDiscovery.NodeRemovalClusterStateTaskExecutor executor = final ZenDiscovery.NodeRemovalClusterStateTaskExecutor executor =
new ZenDiscovery.NodeRemovalClusterStateTaskExecutor(allocationService, electMasterService, rejoin, logger) { new ZenDiscovery.NodeRemovalClusterStateTaskExecutor(allocationService, electMasterService, submitRejoin, logger) {
@Override @Override
ClusterState remainingNodesClusterState(ClusterState currentState, DiscoveryNodes.Builder remainingNodesBuilder) { ClusterState remainingNodesClusterState(ClusterState currentState, DiscoveryNodes.Builder remainingNodesBuilder) {
remainingNodesClusterState.set(super.remainingNodesClusterState(currentState, remainingNodesBuilder)); remainingNodesClusterState.set(super.remainingNodesClusterState(currentState, remainingNodesBuilder));
@ -117,11 +113,11 @@ public class NodeRemovalClusterStateTaskExecutorTests extends ESTestCase {
// ensure that we did not reroute // ensure that we did not reroute
verifyNoMoreInteractions(allocationService); verifyNoMoreInteractions(allocationService);
assertTrue(rejoined.get()); assertTrue(rejoinCalled.get());
assertThat(result.resultingState, equalTo(rejoinedClusterState.get())); assertThat(result.resultingState, equalTo(clusterState));
for (final ZenDiscovery.NodeRemovalClusterStateTaskExecutor.Task task : tasks) { for (final ZenDiscovery.NodeRemovalClusterStateTaskExecutor.Task task : tasks) {
assertNull(result.resultingState.nodes().get(task.node().getId())); assertNotNull(result.resultingState.nodes().get(task.node().getId()));
} }
} }
@ -133,14 +129,11 @@ public class NodeRemovalClusterStateTaskExecutorTests extends ESTestCase {
when(allocationService.deassociateDeadNodes(any(ClusterState.class), eq(true), any(String.class))) when(allocationService.deassociateDeadNodes(any(ClusterState.class), eq(true), any(String.class)))
.thenAnswer(im -> im.getArguments()[0]); .thenAnswer(im -> im.getArguments()[0]);
final BiFunction<ClusterState, String, ClusterState> rejoin = (cs, r) -> { final Consumer<String> submitRejoin = source -> fail("rejoin should not be invoked");
fail("rejoin should not be invoked");
return cs;
};
final AtomicReference<ClusterState> remainingNodesClusterState = new AtomicReference<>(); final AtomicReference<ClusterState> remainingNodesClusterState = new AtomicReference<>();
final ZenDiscovery.NodeRemovalClusterStateTaskExecutor executor = final ZenDiscovery.NodeRemovalClusterStateTaskExecutor executor =
new ZenDiscovery.NodeRemovalClusterStateTaskExecutor(allocationService, electMasterService, rejoin, logger) { new ZenDiscovery.NodeRemovalClusterStateTaskExecutor(allocationService, electMasterService, submitRejoin, logger) {
@Override @Override
ClusterState remainingNodesClusterState(ClusterState currentState, DiscoveryNodes.Builder remainingNodesBuilder) { ClusterState remainingNodesClusterState(ClusterState currentState, DiscoveryNodes.Builder remainingNodesBuilder) {
remainingNodesClusterState.set(super.remainingNodesClusterState(currentState, remainingNodesBuilder)); remainingNodesClusterState.set(super.remainingNodesClusterState(currentState, remainingNodesBuilder));