From 79542a924c9c7a3568b9f0e72607ec04cb6e5a52 Mon Sep 17 00:00:00 2001 From: Martijn van Groningen Date: Tue, 12 Oct 2021 12:17:39 +0200 Subject: [PATCH] Speedup computing cluster health (#78969) In cases the status is not GREEN. Instead of building a list of all shard routings and then counting the total and active number of shards, use the RoutingNodes (which should already be built) that can compute these numbers almost for free. Relates to #77466 --- .../cluster/health/ClusterStateHealth.java | 13 ++++--------- .../cluster/routing/RoutingNodes.java | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/cluster/health/ClusterStateHealth.java b/server/src/main/java/org/elasticsearch/cluster/health/ClusterStateHealth.java index dde0620f85f49..cab509c3c46e9 100644 --- a/server/src/main/java/org/elasticsearch/cluster/health/ClusterStateHealth.java +++ b/server/src/main/java/org/elasticsearch/cluster/health/ClusterStateHealth.java @@ -10,7 +10,7 @@ import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexMetadata; import org.elasticsearch.cluster.routing.IndexRoutingTable; -import org.elasticsearch.cluster.routing.ShardRouting; +import org.elasticsearch.cluster.routing.RoutingNodes; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.Writeable; @@ -20,7 +20,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.Objects; @@ -104,13 +103,9 @@ public ClusterStateHealth(final ClusterState clusterState, final String[] concre if (computeStatus.equals(ClusterHealthStatus.GREEN)) { this.activeShardsPercent = 100; } else { - List shardRoutings = clusterState.getRoutingTable().allShards(); - int activeShardCount = 0; - int totalShardCount = 0; - for (ShardRouting shardRouting : shardRoutings) { - if (shardRouting.active()) activeShardCount++; - totalShardCount++; - } + RoutingNodes routingNodes = clusterState.getRoutingNodes(); + int activeShardCount = routingNodes.getActiveShardCount(); + int totalShardCount = routingNodes.getTotalShardCount(); this.activeShardsPercent = (((double) activeShardCount) / totalShardCount) * 100; } } diff --git a/server/src/main/java/org/elasticsearch/cluster/routing/RoutingNodes.java b/server/src/main/java/org/elasticsearch/cluster/routing/RoutingNodes.java index 965993955aeef..c728bed0e31b4 100644 --- a/server/src/main/java/org/elasticsearch/cluster/routing/RoutingNodes.java +++ b/server/src/main/java/org/elasticsearch/cluster/routing/RoutingNodes.java @@ -72,6 +72,10 @@ public class RoutingNodes implements Iterable { private int relocatingShards = 0; + private int activeShardCount = 0; + + private int totalShardCount = 0; + private final Map> attributeValuesByAttribute = new HashMap<>(); private final Map recoveriesPerNode = new HashMap<>(); @@ -95,6 +99,7 @@ public RoutingNodes(ClusterState clusterState, boolean readOnly) { for (IndexShardRoutingTable indexShard : indexRoutingTable) { assert indexShard.primary != null; for (ShardRouting shard : indexShard) { + totalShardCount++; // to get all the shards belonging to an index, including the replicas, // we define a replica set and keep track of it. A replica set is identified // by the ShardId, as this is common for primary and replicas. @@ -107,6 +112,9 @@ public RoutingNodes(ClusterState clusterState, boolean readOnly) { throw new IllegalArgumentException("Cannot have two different shards with same shard id on same node"); } assignedShardsAdd(shard); + if (shard.active()) { + activeShardCount++; + } if (shard.relocating()) { relocatingShards++; // LinkedHashMap to preserve order. @@ -273,6 +281,14 @@ public int getRelocatingShardCount() { return relocatingShards; } + public int getActiveShardCount() { + return activeShardCount; + } + + public int getTotalShardCount() { + return totalShardCount; + } + /** * Returns all shards that are not in the state UNASSIGNED with the same shard * ID as the given shard.