From 8277f61f0e6bd5d0b99e0fd35073c788bfe38379 Mon Sep 17 00:00:00 2001 From: patsonluk Date: Mon, 24 Jul 2023 18:37:29 -0700 Subject: [PATCH 1/3] Added Overseer node role to solrbench --- src/main/java/StressMain.java | 3 +- .../solr/benchmarks/BenchmarksMain.java | 2 +- .../solr/benchmarks/solrcloud/SolrCloud.java | 79 ++++++++++++++----- 3 files changed, 60 insertions(+), 24 deletions(-) diff --git a/src/main/java/StressMain.java b/src/main/java/StressMain.java index 65f7aa02..86f9b142 100644 --- a/src/main/java/StressMain.java +++ b/src/main/java/StressMain.java @@ -311,8 +311,7 @@ private static Callable taskCallable(Workflow workflow, SolrCloud cloud, Map restartNodes; if (type.restartAllNodes) { - restartNodes = new ArrayList<>(cloud.queryNodes); - restartNodes.addAll(cloud.nodes); + restartNodes = new ArrayList<>(cloud.nodes); log.info("Restarting " + restartNodes.size() + " node(s)"); } else { String nodeIndex = resolveString(resolveString(type.restartSolrNode, params), workflow.globalConstants); diff --git a/src/main/java/org/apache/solr/benchmarks/BenchmarksMain.java b/src/main/java/org/apache/solr/benchmarks/BenchmarksMain.java index 49303d56..54c0bb7e 100644 --- a/src/main/java/org/apache/solr/benchmarks/BenchmarksMain.java +++ b/src/main/java/org/apache/solr/benchmarks/BenchmarksMain.java @@ -72,7 +72,7 @@ public static void runQueryBenchmarks(List queryBenchmarks, Stri for (QueryBenchmark benchmark : queryBenchmarks) { log.info("Query Benchmark name: " + benchmark.name); results.get("query-benchmarks").put(benchmark.name, new ArrayList()); - List queryNodes = solrCloud.queryNodes.isEmpty() ? solrCloud.nodes : solrCloud.queryNodes; + List queryNodes = solrCloud.getNodesByRole(SolrCloud.NodeRole.COORDINATOR); String baseUrl = queryNodes.get(benchmark.queryNode-1).getBaseUrl(); log.info("Query base URL " + baseUrl); for (int threads = benchmark.minThreads; threads <= benchmark.maxThreads; threads++) { diff --git a/src/main/java/org/apache/solr/benchmarks/solrcloud/SolrCloud.java b/src/main/java/org/apache/solr/benchmarks/solrcloud/SolrCloud.java index 32b9c73b..a9953ca4 100644 --- a/src/main/java/org/apache/solr/benchmarks/solrcloud/SolrCloud.java +++ b/src/main/java/org/apache/solr/benchmarks/solrcloud/SolrCloud.java @@ -28,6 +28,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; @@ -64,9 +65,14 @@ public class SolrCloud { private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); Zookeeper zookeeper; - public List nodes = Collections.synchronizedList(new ArrayList()); + public List nodes = Collections.synchronizedList(new ArrayList()); //all nodes - public List queryNodes = Collections.synchronizedList(new ArrayList()); + public enum NodeRole { + DATA, COORDINATOR, OVERSEER + } + + //Node list by role, though unlikely, a node can appear in multiple lists, ie a node with multiple roles + public Map> nodesByRole = new HashMap<>(); private Set configsets = new HashSet<>(); @@ -185,32 +191,39 @@ public void init() throws Exception { zookeeper = new GenericZookeeper(tokens[0], tokens.length > 1 ? Integer.parseInt(tokens[1]) : null, cluster.externalSolrConfig.zkAdminPort, cluster.externalSolrConfig.zkChroot); try (CloudSolrClient client = new CloudSolrClient.Builder().withZkHost(cluster.externalSolrConfig.zkHost).withZkChroot(cluster.externalSolrConfig.zkChroot).build()) { - Collection liveNodes = getExternalDataNodes(client); - for (String liveNode: liveNodes) { + for (String liveNode : client.getClusterStateProvider().getLiveNodes()) { nodes.add(new ExternalSolrNode( liveNode.split("_solr")[0].split(":")[0], Integer.valueOf(liveNode.split("_solr")[0].split(":")[1]), cluster.externalSolrConfig.sshUserName, cluster.externalSolrConfig.restartScript)); } - try { - Collection queryNodeList = getExternalQueryNodes(client); - for (String queryNode : queryNodeList) { - queryNodes.add(new ExternalSolrNode( - queryNode.split("_solr")[0].split(":")[0], - Integer.valueOf(queryNode.split("_solr")[0].split(":")[1]), - cluster.externalSolrConfig.sshUserName, - cluster.externalSolrConfig.restartScript)); - } - } catch (KeeperException e) { - if (e.code() == KeeperException.Code.NONODE) { - log.info("No /live_query_nodes. Skipping query nodes."); - } else { - throw e; - } + List dataNodes = getExternalDataNodes(client).stream().map(dataNode -> new ExternalSolrNode( + dataNode.split("_solr")[0].split(":")[0], + Integer.valueOf(dataNode.split("_solr")[0].split(":")[1]), + cluster.externalSolrConfig.sshUserName, + cluster.externalSolrConfig.restartScript)).collect(Collectors.toList()); + if (!dataNodes.isEmpty()) { + nodesByRole.put(NodeRole.DATA, dataNodes); + } + List queryNodes = getExternalQueryNodes(client).stream().map(queryNode -> new ExternalSolrNode( + queryNode.split("_solr")[0].split(":")[0], + Integer.valueOf(queryNode.split("_solr")[0].split(":")[1]), + cluster.externalSolrConfig.sshUserName, + cluster.externalSolrConfig.restartScript)).collect(Collectors.toList()); + if (!queryNodes.isEmpty()) { + nodesByRole.put(NodeRole.COORDINATOR, queryNodes); + } + List overseerNodes = getExternalPreferredOverseerNodes(client).stream().map(overseerNode -> new ExternalSolrNode( + overseerNode.split("_solr")[0].split(":")[0], + Integer.valueOf(overseerNode.split("_solr")[0].split(":")[1]), + cluster.externalSolrConfig.sshUserName, + cluster.externalSolrConfig.restartScript)).collect(Collectors.toList()); + if (!queryNodes.isEmpty()) { + nodesByRole.put(NodeRole.OVERSEER, overseerNodes); } } - log.info("Cluster initialized with data nodes: " + nodes + ", query nodes: " + queryNodes + ", zkHost: " + zookeeper); + log.info("Cluster initialized with data nodes: " + nodes + ", zkHost: " + zookeeper + ", nodes by role: " + nodesByRole); } @@ -230,7 +243,7 @@ private Collection getExternalDataNodes(CloudSolrClient client) { } return client.getClusterStateProvider().getLiveNodes(); } - private Collection getExternalQueryNodes(CloudSolrClient client) throws InterruptedException, KeeperException { + private Collection getExternalQueryNodes(CloudSolrClient client) { try { if (client.getZkStateReader().getZkClient().exists("/node_roles/coordinator/on", true)) { List liveNodes = new ArrayList(client.getClusterStateProvider().getLiveNodes()); @@ -242,9 +255,29 @@ private Collection getExternalQueryNodes(CloudSolrClient client) throws } catch (Exception e) { //ok, just use the /live_query_nodes } + try { return client.getZkStateReader().getZkClient().getChildren("/live_query_nodes", null, true); + } catch (Exception e) { + log.warn("Failed to look up query nodes. Skipping"); + return Collections.emptyList(); + } } + private Collection getExternalPreferredOverseerNodes(CloudSolrClient client) { + try { + if (client.getZkStateReader().getZkClient().exists("/node_roles/overseer/preferred", true)) { + List liveNodes = new ArrayList(client.getClusterStateProvider().getLiveNodes()); + liveNodes.retainAll(client.getZkStateReader().getZkClient().getChildren("/node_roles/overseer/preferred", null, true)); + if (!liveNodes.isEmpty()) { + return liveNodes; + } + } + } catch (Exception e) { + log.warn("Failed to look up overseer nodes. Skipping"); + } + return Collections.emptyList(); + } + List getSolrNodesFromTFState() throws JsonMappingException, JsonProcessingException, IOException { List out = new ArrayList(); @@ -478,6 +511,10 @@ public SolrParams getParams() { } + public List getNodesByRole(NodeRole role) { + return nodesByRole.containsKey(role) ? nodesByRole.get(role) : nodes; + } + public String getProvisioningMethod() { return cluster.provisioningMethod; } From b8f6fe25f70a0728a8270aa6f4b48a6f230543d8 Mon Sep 17 00:00:00 2001 From: patsonluk Date: Tue, 25 Jul 2023 11:09:57 -0700 Subject: [PATCH 2/3] Minor correction to debug message --- .../java/org/apache/solr/benchmarks/solrcloud/SolrCloud.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/apache/solr/benchmarks/solrcloud/SolrCloud.java b/src/main/java/org/apache/solr/benchmarks/solrcloud/SolrCloud.java index a9953ca4..cf8125ec 100644 --- a/src/main/java/org/apache/solr/benchmarks/solrcloud/SolrCloud.java +++ b/src/main/java/org/apache/solr/benchmarks/solrcloud/SolrCloud.java @@ -223,7 +223,7 @@ public void init() throws Exception { nodesByRole.put(NodeRole.OVERSEER, overseerNodes); } } - log.info("Cluster initialized with data nodes: " + nodes + ", zkHost: " + zookeeper + ", nodes by role: " + nodesByRole); + log.info("Cluster initialized with nodes: " + nodes + ", zkHost: " + zookeeper + ", nodes by role: " + nodesByRole); } From c1518aaa808a25dd46d87feb9dfe85872ed959f4 Mon Sep 17 00:00:00 2001 From: patsonluk Date: Tue, 25 Jul 2023 12:24:57 -0700 Subject: [PATCH 3/3] Javadoc for getNodesByRole --- .../org/apache/solr/benchmarks/solrcloud/SolrCloud.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/org/apache/solr/benchmarks/solrcloud/SolrCloud.java b/src/main/java/org/apache/solr/benchmarks/solrcloud/SolrCloud.java index cf8125ec..526e7f17 100644 --- a/src/main/java/org/apache/solr/benchmarks/solrcloud/SolrCloud.java +++ b/src/main/java/org/apache/solr/benchmarks/solrcloud/SolrCloud.java @@ -511,6 +511,13 @@ public SolrParams getParams() { } + /** + * Gets the list of nodes by its NodeRole. If NodeRole is not supported, then return all nodes. + * + * Take note that currently only ExternalSolrNode has support for NodeRole. + * @param role + * @return + */ public List getNodesByRole(NodeRole role) { return nodesByRole.containsKey(role) ? nodesByRole.get(role) : nodes; }