mirror of
https://github.com/Graylog2/graylog2-server.git
synced 2026-03-13 09:32:21 +08:00
Remove all datanode leader node usages (#19170)
* Remove all datanode leader node usages * Added changelog * Fixed rest client injection * fix datanode isLeader in builder * Remove leader selector in datanode proxy implementations
This commit is contained in:
@@ -19,7 +19,6 @@ package org.graylog.datanode.bindings;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.multibindings.Multibinder;
|
||||
import org.graylog.datanode.bootstrap.preflight.DataNodeConfigurationPeriodical;
|
||||
import org.graylog.datanode.periodicals.ClusterManagerDiscovery;
|
||||
import org.graylog.datanode.periodicals.MetricsCollector;
|
||||
import org.graylog.datanode.periodicals.NodePingPeriodical;
|
||||
import org.graylog.datanode.periodicals.OpensearchNodeHeartbeat;
|
||||
@@ -34,7 +33,6 @@ public class PeriodicalBindings extends AbstractModule {
|
||||
periodicalBinder.addBinding().to(ClusterEventPeriodical.class);
|
||||
periodicalBinder.addBinding().to(ClusterEventCleanupPeriodical.class);
|
||||
periodicalBinder.addBinding().to(OpensearchNodeHeartbeat.class);
|
||||
periodicalBinder.addBinding().to(ClusterManagerDiscovery.class);
|
||||
// periodicalBinder.addBinding().to(UserSessionTerminationPeriodical.class);
|
||||
periodicalBinder.addBinding().to(NodePingPeriodical.class);
|
||||
periodicalBinder.addBinding().to(DataNodeConfigurationPeriodical.class);
|
||||
|
||||
@@ -139,7 +139,6 @@ public class Server extends ServerBootstrap {
|
||||
// always set leader to "false" on startup and let the NodePingPeriodical take care of it later
|
||||
nodeService.registerServer(DataNodeDto.Builder.builder()
|
||||
.setId(nodeId.getNodeId())
|
||||
.setLeader(false)
|
||||
.setTransportAddress(configuration.getHttpPublishUri().toString())
|
||||
.setHostname(Tools.getLocalCanonicalHostname())
|
||||
.setDataNodeStatus(DataNodeStatus.STARTING)
|
||||
|
||||
@@ -19,6 +19,6 @@ package org.graylog.datanode.opensearch;
|
||||
import org.graylog.datanode.opensearch.statemachine.OpensearchState;
|
||||
import org.graylog.datanode.process.ProcessInformation;
|
||||
|
||||
public record OpensearchInfo(String nodeName, OpensearchState state, boolean isLeaderNode, String restBaseUrl,
|
||||
public record OpensearchInfo(String nodeName, OpensearchState state, String restBaseUrl,
|
||||
ProcessInformation process) {
|
||||
}
|
||||
|
||||
@@ -34,9 +34,6 @@ public interface OpensearchProcess extends ManagableProcess<OpensearchConfigurat
|
||||
Optional<RestHighLevelClient> restClient();
|
||||
|
||||
Optional<OpenSearchClient> openSearchClient();
|
||||
|
||||
boolean isLeaderNode();
|
||||
void setLeaderNode(boolean isManagerNode);
|
||||
List<String> stdOutLogs();
|
||||
List<String> stdErrLogs();
|
||||
|
||||
|
||||
@@ -70,7 +70,6 @@ class OpensearchProcessImpl implements OpensearchProcess, ProcessListener {
|
||||
|
||||
private final DatanodeConfiguration datanodeConfiguration;
|
||||
|
||||
private boolean isLeaderNode;
|
||||
private OpensearchCommandLineProcess commandLineProcess;
|
||||
|
||||
private final Queue<String> stdout;
|
||||
@@ -116,7 +115,7 @@ class OpensearchProcessImpl implements OpensearchProcess, ProcessListener {
|
||||
}
|
||||
|
||||
public OpensearchInfo processInfo() {
|
||||
return new OpensearchInfo(configuration.getDatanodeNodeName(), processState.getState(), isLeaderNode, getOpensearchBaseUrl().toString(), commandLineProcess != null ? commandLineProcess.processInfo() : ProcessInformation.empty());
|
||||
return new OpensearchInfo(configuration.getDatanodeNodeName(), processState.getState(), getOpensearchBaseUrl().toString(), commandLineProcess != null ? commandLineProcess.processInfo() : ProcessInformation.empty());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -156,15 +155,6 @@ class OpensearchProcessImpl implements OpensearchProcess, ProcessListener {
|
||||
this.processState.getTracerAggregator().addTracer((StateMachineTracer) stateMachineTracer);
|
||||
}
|
||||
|
||||
public void setLeaderNode(boolean isLeaderNode) {
|
||||
this.isLeaderNode = isLeaderNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeaderNode() {
|
||||
return isLeaderNode;
|
||||
}
|
||||
|
||||
public boolean isInState(OpensearchState expectedState) {
|
||||
return this.processState.getState().equals(expectedState);
|
||||
}
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Graylog, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Server Side Public License, version 1,
|
||||
* as published by MongoDB, Inc.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* Server Side Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the Server Side Public License
|
||||
* along with this program. If not, see
|
||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
||||
*/
|
||||
package org.graylog.datanode.periodicals;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import org.graylog.datanode.Configuration;
|
||||
import org.graylog.datanode.configuration.DatanodeConfiguration;
|
||||
import org.graylog.datanode.opensearch.OpensearchProcess;
|
||||
import org.graylog.datanode.opensearch.statemachine.OpensearchState;
|
||||
import org.graylog.shaded.opensearch2.org.opensearch.client.Request;
|
||||
import org.graylog.shaded.opensearch2.org.opensearch.client.Response;
|
||||
import org.graylog.shaded.opensearch2.org.opensearch.client.RestHighLevelClient;
|
||||
import org.graylog2.plugin.periodical.Periodical;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
@Singleton
|
||||
public class ClusterManagerDiscovery extends Periodical {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ClusterManagerDiscovery.class);
|
||||
private final DatanodeConfiguration datanodeConfiguration;
|
||||
private final OpensearchProcess managedOpenSearch;
|
||||
private final ObjectMapper objectMapper;
|
||||
private final Configuration configuration;
|
||||
|
||||
@Inject
|
||||
public ClusterManagerDiscovery(DatanodeConfiguration datanodeConfiguration, OpensearchProcess managedOpenSearch, ObjectMapper objectMapper, Configuration configuration) {
|
||||
this.datanodeConfiguration = datanodeConfiguration;
|
||||
this.managedOpenSearch = managedOpenSearch;
|
||||
this.objectMapper = objectMapper;
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
// This method is "synchronized" because we are also calling it directly in AutomaticLeaderElectionService
|
||||
public synchronized void doRun() {
|
||||
if (managedOpenSearch.isInState(OpensearchState.AVAILABLE)) {
|
||||
final Boolean isManagerNode = getClusterStateResponse(managedOpenSearch)
|
||||
.map(r -> r.nodes().get(r.clusterManagerNode()))
|
||||
.map(managerNode -> configuration.getDatanodeNodeName().equals(managerNode.name()))
|
||||
.orElse(false);
|
||||
managedOpenSearch.setLeaderNode(isManagerNode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Optional<ClusterStateResponse> getClusterStateResponse(OpensearchProcess process) {
|
||||
return process.restClient().flatMap(this::requestClusterState);
|
||||
}
|
||||
|
||||
private Optional<ClusterStateResponse> requestClusterState(RestHighLevelClient client) {
|
||||
try {
|
||||
final Response response = client.getLowLevelClient().performRequest(new Request("GET", "_cluster/state/"));
|
||||
final ClusterStateResponse state = objectMapper.readValue(response.getEntity().getContent(), ClusterStateResponse.class);
|
||||
return Optional.of(state);
|
||||
} catch (IOException e) {
|
||||
LOG.warn("Failed to obtain cluster state response", e);
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Logger getLogger() {
|
||||
return LOG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean runsForever() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stopOnGracefulShutdown() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean leaderOnly() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startOnThisNode() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDaemon() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInitialDelaySeconds() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPeriodSeconds() {
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
@@ -21,9 +21,9 @@ import com.google.common.collect.ImmutableMap;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import jakarta.inject.Inject;
|
||||
import org.graylog.datanode.Configuration;
|
||||
import org.graylog.datanode.opensearch.OpensearchProcess;
|
||||
import org.graylog.datanode.metrics.ClusterStatMetricsCollector;
|
||||
import org.graylog.datanode.metrics.NodeMetricsCollector;
|
||||
import org.graylog.datanode.opensearch.OpensearchProcess;
|
||||
import org.graylog.datanode.opensearch.statemachine.OpensearchState;
|
||||
import org.graylog.shaded.opensearch2.org.joda.time.DateTime;
|
||||
import org.graylog.shaded.opensearch2.org.joda.time.DateTimeZone;
|
||||
@@ -31,7 +31,9 @@ import org.graylog.shaded.opensearch2.org.opensearch.action.index.IndexRequest;
|
||||
import org.graylog.shaded.opensearch2.org.opensearch.action.index.IndexResponse;
|
||||
import org.graylog.shaded.opensearch2.org.opensearch.action.search.SearchRequest;
|
||||
import org.graylog.shaded.opensearch2.org.opensearch.action.search.SearchResponse;
|
||||
import org.graylog.shaded.opensearch2.org.opensearch.client.Request;
|
||||
import org.graylog.shaded.opensearch2.org.opensearch.client.RequestOptions;
|
||||
import org.graylog.shaded.opensearch2.org.opensearch.client.Response;
|
||||
import org.graylog.shaded.opensearch2.org.opensearch.client.RestHighLevelClient;
|
||||
import org.graylog.shaded.opensearch2.org.opensearch.core.action.ActionListener;
|
||||
import org.graylog.shaded.opensearch2.org.opensearch.index.query.QueryBuilders;
|
||||
@@ -50,6 +52,7 @@ import java.lang.management.MemoryUsage;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public class MetricsCollector extends Periodical {
|
||||
|
||||
@@ -59,7 +62,6 @@ public class MetricsCollector extends Periodical {
|
||||
private NodeMetricsCollector nodeStatMetricsCollector;
|
||||
private ClusterStatMetricsCollector clusterStatMetricsCollector;
|
||||
private final ObjectMapper objectMapper;
|
||||
private boolean isLeader;
|
||||
|
||||
@Inject
|
||||
public MetricsCollector(OpensearchProcess process, Configuration configuration, ObjectMapper objectMapper) {
|
||||
@@ -110,8 +112,6 @@ public class MetricsCollector extends Periodical {
|
||||
process.restClient().ifPresent(client -> {
|
||||
this.nodeStatMetricsCollector = new NodeMetricsCollector(client, objectMapper);
|
||||
this.clusterStatMetricsCollector = new ClusterStatMetricsCollector(client, objectMapper);
|
||||
this.isLeader = process.isLeaderNode();
|
||||
|
||||
final IndexRequest indexRequest = new IndexRequest(configuration.getMetricsStream());
|
||||
Map<String, Object> metrics = new HashMap<String, Object>();
|
||||
metrics.put(configuration.getMetricsTimestamp(), new DateTime(DateTimeZone.UTC));
|
||||
@@ -122,17 +122,36 @@ public class MetricsCollector extends Periodical {
|
||||
indexRequest.source(metrics);
|
||||
indexDocument(client, indexRequest);
|
||||
|
||||
if (isLeader) {
|
||||
if (isManagerNode(process)) {
|
||||
metrics = new HashMap<>(clusterStatMetricsCollector.getClusterMetrics(getPreviousMetricsForCluster(client)));
|
||||
metrics.put(configuration.getMetricsTimestamp(), new DateTime(DateTimeZone.UTC));
|
||||
indexRequest.source(metrics);
|
||||
indexDocument(client, indexRequest);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isManagerNode(OpensearchProcess process) {
|
||||
return process.restClient()
|
||||
.flatMap(this::requestClusterState)
|
||||
.map(r -> r.nodes().get(r.clusterManagerNode()))
|
||||
.map(managerNode -> configuration.getDatanodeNodeName().equals(managerNode.name()))
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
|
||||
private Optional<ClusterStateResponse> requestClusterState(RestHighLevelClient client) {
|
||||
try {
|
||||
final Response response = client.getLowLevelClient().performRequest(new Request("GET", "_cluster/state/"));
|
||||
final ClusterStateResponse state = objectMapper.readValue(response.getEntity().getContent(), ClusterStateResponse.class);
|
||||
return Optional.of(state);
|
||||
} catch (IOException e) {
|
||||
LOG.warn("Failed to obtain cluster state response", e);
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private void addJvmMetrics(Map<String, Object> metrics) {
|
||||
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
|
||||
metrics.put("dn_heap_usage", calcUsage(memoryMXBean.getHeapMemoryUsage()));
|
||||
|
||||
@@ -40,7 +40,6 @@ public class NodePingPeriodical extends Periodical {
|
||||
private final Supplier<URI> opensearchBaseUri;
|
||||
private final Supplier<String> opensearchClusterUri;
|
||||
private final Supplier<String> datanodeRestApiUri;
|
||||
private final Supplier<Boolean> isLeader;
|
||||
private final Configuration configuration;
|
||||
private final Supplier<OpensearchState> processState;
|
||||
|
||||
@@ -54,7 +53,6 @@ public class NodePingPeriodical extends Periodical {
|
||||
managedOpenSearch::getOpensearchBaseUrl,
|
||||
managedOpenSearch::getOpensearchClusterUrl,
|
||||
managedOpenSearch::getDatanodeRestApiUrl,
|
||||
managedOpenSearch::isLeaderNode,
|
||||
() -> managedOpenSearch.processInfo().state()
|
||||
);
|
||||
}
|
||||
@@ -66,7 +64,6 @@ public class NodePingPeriodical extends Periodical {
|
||||
Supplier<URI> opensearchBaseUri,
|
||||
Supplier<String> opensearchClusterUri,
|
||||
Supplier<String> datanodeRestApiUri,
|
||||
Supplier<Boolean> isLeader,
|
||||
Supplier<OpensearchState> processState
|
||||
) {
|
||||
this.nodeService = nodeService;
|
||||
@@ -74,7 +71,6 @@ public class NodePingPeriodical extends Periodical {
|
||||
this.opensearchBaseUri = opensearchBaseUri;
|
||||
this.opensearchClusterUri = opensearchClusterUri;
|
||||
this.datanodeRestApiUri = datanodeRestApiUri;
|
||||
this.isLeader = isLeader;
|
||||
this.configuration = configuration;
|
||||
this.processState = processState;
|
||||
}
|
||||
@@ -124,7 +120,6 @@ public class NodePingPeriodical extends Periodical {
|
||||
public void doRun() {
|
||||
final DataNodeDto dto = DataNodeDto.Builder.builder()
|
||||
.setId(nodeId.getNodeId())
|
||||
.setLeader(isLeader.get())
|
||||
.setTransportAddress(opensearchBaseUri.get().toString())
|
||||
.setClusterAddress(opensearchClusterUri.get())
|
||||
.setDataNodeStatus(processState.get().getDataNodeStatus())
|
||||
@@ -139,7 +134,6 @@ public class NodePingPeriodical extends Periodical {
|
||||
private void registerServer() {
|
||||
final boolean registrationSucceeded = nodeService.registerServer(DataNodeDto.Builder.builder()
|
||||
.setId(nodeId.getNodeId())
|
||||
.setLeader(isLeader.get())
|
||||
.setTransportAddress(opensearchBaseUri.get().toString())
|
||||
.setClusterAddress(opensearchClusterUri.get())
|
||||
.setHostname(configuration.getHostname())
|
||||
|
||||
Reference in New Issue
Block a user