You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by dw...@apache.org on 2021/03/10 09:56:12 UTC
[lucene] 01/04: SOLR-15130: WIP.
This is an automated email from the ASF dual-hosted git repository.
dweiss pushed a commit to branch jira/solr-15130
in repository https://gitbox.apache.org/repos/asf/lucene.git
commit 51aa6c331e08d8d7e71b65c9baee17c2a3ba5638
Author: Andrzej Bialecki <ab...@apache.org>
AuthorDate: Mon Feb 8 15:25:28 2021 +0100
SOLR-15130: WIP.
---
.../placement/plugins/AffinityPlacementConfig.java | 3 ++
.../plugins/AffinityPlacementFactory.java | 40 +++++++++++++++++++---
2 files changed, 39 insertions(+), 4 deletions(-)
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/plugins/AffinityPlacementConfig.java b/solr/core/src/java/org/apache/solr/cluster/placement/plugins/AffinityPlacementConfig.java
index d9579bc..062750a 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/plugins/AffinityPlacementConfig.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/plugins/AffinityPlacementConfig.java
@@ -19,6 +19,7 @@ package org.apache.solr.cluster.placement.plugins;
import org.apache.solr.cluster.placement.PlacementPluginConfig;
import org.apache.solr.common.annotation.JsonProperty;
+import org.apache.solr.common.params.CollectionAdminParams;
import java.util.Map;
import java.util.Objects;
@@ -28,6 +29,8 @@ import java.util.Objects;
*/
public class AffinityPlacementConfig implements PlacementPluginConfig {
+ public static final String COLLECTION_NODE_TYPE_PROPERTY = CollectionAdminParams.PROPERTY_PREFIX + "placement.affinity.node_type";
+
public static final long DEFAULT_MINIMAL_FREE_DISK_GB = 20L;
public static final long DEFAULT_PRIORITIZED_FREE_DISK_GB = 100L;
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/plugins/AffinityPlacementFactory.java b/solr/core/src/java/org/apache/solr/cluster/placement/plugins/AffinityPlacementFactory.java
index eaec4ab..64aa9d5 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/plugins/AffinityPlacementFactory.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/plugins/AffinityPlacementFactory.java
@@ -23,6 +23,7 @@ import org.apache.solr.cluster.*;
import org.apache.solr.cluster.placement.*;
import org.apache.solr.cluster.placement.impl.NodeMetricImpl;
import org.apache.solr.common.util.Pair;
+import org.apache.solr.common.util.StrUtils;
import org.apache.solr.common.util.SuppressForbidden;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -131,6 +132,8 @@ public class AffinityPlacementFactory implements PlacementPluginFactory<Affinity
*/
public static final String REPLICA_TYPE_SYSPROP = "replica_type";
+ public static final String NODE_TYPE_SYSPROP = "node_type";
+
/**
* This is the "AZ" name for nodes that do not define an AZ. Should not match a real AZ name (I think we're safe)
*/
@@ -210,17 +213,23 @@ public class AffinityPlacementFactory implements PlacementPluginFactory<Affinity
Set<Node> nodes = request.getTargetNodes();
SolrCollection solrCollection = request.getCollection();
- nodes = filterNodesWithCollection(placementContext.getCluster(), request, nodes);
-
// Request all needed attributes
AttributeFetcher attributeFetcher = placementContext.getAttributeFetcher();
- attributeFetcher.requestNodeSystemProperty(AVAILABILITY_ZONE_SYSPROP).requestNodeSystemProperty(REPLICA_TYPE_SYSPROP);
+ attributeFetcher
+ .requestNodeSystemProperty(AVAILABILITY_ZONE_SYSPROP)
+ .requestNodeSystemProperty(NODE_TYPE_SYSPROP)
+ .requestNodeSystemProperty(REPLICA_TYPE_SYSPROP);
attributeFetcher
.requestNodeMetric(NodeMetricImpl.NUM_CORES)
.requestNodeMetric(NodeMetricImpl.FREE_DISK_GB);
attributeFetcher.fetchFrom(nodes);
final AttributeValues attrValues = attributeFetcher.fetchAttributes();
+ // filter out nodes that don't meet the `withCollection` constraint
+ nodes = filterNodesWithCollection(placementContext.getCluster(), request, attrValues, nodes);
+ // filter out nodes that don't match the "node types" specified in the collection props
+ nodes = filterNodesByNodeType(placementContext.getCluster(), request, attrValues, nodes);
+
// Split the set of nodes into 3 sets of nodes accepting each replica type (sets can overlap if nodes accept multiple replica types)
// These subsets sets are actually maps, because we capture the number of cores (of any replica type) present on each node.
// Also get the number of currently existing cores per node, so we can keep update as we place new cores to not end up
@@ -632,7 +641,7 @@ public class AffinityPlacementFactory implements PlacementPluginFactory<Affinity
}
}
- private Set<Node> filterNodesWithCollection(Cluster cluster, PlacementRequest request, Set<Node> initialNodes) throws PlacementException {
+ private Set<Node> filterNodesWithCollection(Cluster cluster, PlacementRequest request, AttributeValues attributeValues, Set<Node> initialNodes) throws PlacementException {
// if there's a `withCollection` constraint for this collection then remove nodes
// that are not eligible
String withCollectionName = withCollections.get(request.getCollection().getName());
@@ -658,6 +667,29 @@ public class AffinityPlacementFactory implements PlacementPluginFactory<Affinity
return filteredNodes;
}
+ private Set<Node> filterNodesByNodeType(Cluster cluster, PlacementRequest request, AttributeValues attributeValues, Set<Node> initialNodes) throws PlacementException {
+ String collProperty = request.getCollection().getCustomProperty(AffinityPlacementConfig.COLLECTION_NODE_TYPE_PROPERTY);
+ if (collProperty == null) {
+ // no filtering by node type
+ return initialNodes;
+ }
+ Set<String> collNodeTypes = Set.copyOf(StrUtils.splitSmart(collProperty, ','));
+ Set<Node> filteredNodes = initialNodes.stream()
+ .filter(n -> {
+ Optional<String> nodePropOpt = attributeValues.getSystemProperty(n, AffinityPlacementConfig.COLLECTION_NODE_TYPE_PROPERTY);
+ if (!nodePropOpt.isPresent()) {
+ return false;
+ }
+ Set<String> nodeTypes = Set.copyOf(StrUtils.splitSmart(nodePropOpt.get(), ','));
+ nodeTypes.retainAll(collNodeTypes);
+ return !nodeTypes.isEmpty();
+ }).collect(Collectors.toSet());
+ if (filteredNodes.isEmpty()) {
+ throw new PlacementException("There are no nodes with types: " + collNodeTypes + " expected by collection " + request.getCollection().getName());
+ }
+ return filteredNodes;
+ }
+
/**
* Comparator implementing the placement strategy based on free space and number of cores: we want to place new replicas
* on nodes with the less number of cores, but only if they do have enough disk space (expressed as a threshold value).