You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by is...@apache.org on 2018/02/25 06:24:46 UTC

lucene-solr:master: SOLR-8327: Cluster state caching for nodes not hosting the collection

Repository: lucene-solr
Updated Branches:
  refs/heads/master 29e5b8abc -> b212f2e9b


SOLR-8327: Cluster state caching for nodes not hosting the collection


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/b212f2e9
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/b212f2e9
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/b212f2e9

Branch: refs/heads/master
Commit: b212f2e9b7b5d20ab8d6168b5ddcb164f536d1af
Parents: 29e5b8a
Author: Ishan Chattopadhyaya <is...@apache.org>
Authored: Sun Feb 25 11:54:33 2018 +0530
Committer: Ishan Chattopadhyaya <is...@apache.org>
Committed: Sun Feb 25 11:54:33 2018 +0530

----------------------------------------------------------------------
 solr/CHANGES.txt                                |  2 ++
 .../java/org/apache/solr/cloud/Overseer.java    |  2 +-
 .../org/apache/solr/servlet/HttpSolrCall.java   |  2 +-
 .../apache/solr/common/cloud/ClusterState.java  | 26 +++++++++++++++--
 .../apache/solr/common/cloud/ZkStateReader.java | 30 ++++++++++++++++----
 5 files changed, 53 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b212f2e9/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 57aad64..5c0351e 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -234,6 +234,8 @@ Optimizations
 
 * SOLR-11879: avoid EOFException for empty input streams (noble)
 
+* SOLR-8327: Cluster state caching to avoid live fetch from ZK of cluster state for forwarding requests on nodes
+  that do not host any replica of the collection (Jessica Cheng Mallet, John Gallagher, Noble Paul, Ishan Chattopadhyaya)
 
 Other Changes
 ----------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b212f2e9/solr/core/src/java/org/apache/solr/cloud/Overseer.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/Overseer.java b/solr/core/src/java/org/apache/solr/cloud/Overseer.java
index b94af27..608fb20 100644
--- a/solr/core/src/java/org/apache/solr/cloud/Overseer.java
+++ b/solr/core/src/java/org/apache/solr/cloud/Overseer.java
@@ -70,7 +70,7 @@ public class Overseer implements SolrCloseable {
   public static final String QUEUE_OPERATION = "operation";
 
   // System properties are used in tests to make them run fast
-  public static final int STATE_UPDATE_DELAY = Integer.getInteger("solr.OverseerStateUpdateDelay", 2000);  // delay between cloud state updates
+  public static final int STATE_UPDATE_DELAY = ZkStateReader.STATE_UPDATE_DELAY;
   public static final int STATE_UPDATE_BATCH_SIZE = Integer.getInteger("solr.OverseerStateUpdateBatchSize", 10000);
   public static final int STATE_UPDATE_MAX_QUEUE = 20000;
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b212f2e9/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
index 6b10f58..50fa71c 100644
--- a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
+++ b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
@@ -819,7 +819,7 @@ public class HttpSolrCall {
     ZkStateReader zkStateReader = cores.getZkController().getZkStateReader();
 
     ClusterState clusterState = zkStateReader.getClusterState();
-    DocCollection collection = clusterState.getCollectionOrNull(collectionName);
+    DocCollection collection = clusterState.getCollectionOrNull(collectionName, true);
     if (collection == null) {
       return null;
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b212f2e9/solr/solrj/src/java/org/apache/solr/common/cloud/ClusterState.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/common/cloud/ClusterState.java b/solr/solrj/src/java/org/apache/solr/common/cloud/ClusterState.java
index 4333a00..970d95d 100644
--- a/solr/solrj/src/java/org/apache/solr/common/cloud/ClusterState.java
+++ b/solr/solrj/src/java/org/apache/solr/common/cloud/ClusterState.java
@@ -125,16 +125,27 @@ public class ClusterState implements JSONWriter.Writable {
 
   /**
    * Returns the corresponding {@link DocCollection} object for the given collection name
+   * if such a collection exists. Returns null otherwise.  Equivalent to getCollectionOrNull(collectionName, false)
+   */
+  public DocCollection getCollectionOrNull(String collectionName) {
+    return getCollectionOrNull(collectionName, false);
+  }
+
+  /**
+   * Returns the corresponding {@link DocCollection} object for the given collection name
    * if such a collection exists. Returns null otherwise.
    *
+   * @param collectionName Name of the collection
+   * @param allowCached allow LazyCollectionRefs to use a time-based cached value
+   *
    * Implementation note: This method resolves the collection reference by calling
    * {@link CollectionRef#get()} which may make a call to ZooKeeper. This is necessary
    * because the semantics of how collection list is loaded have changed in SOLR-6629.
    * Please see javadocs in {@link ZkStateReader#refreshCollectionList(Watcher)}
    */
-  public DocCollection getCollectionOrNull(String collectionName) {
+  public DocCollection getCollectionOrNull(String collectionName, boolean allowCached) {
     CollectionRef ref = collectionStates.get(collectionName);
-    return ref == null ? null : ref.get();
+    return ref == null ? null : ref.get(allowCached);
   }
 
   /**
@@ -368,7 +379,18 @@ public class ClusterState implements JSONWriter.Writable {
       this.coll = coll;
     }
 
+    /** Return the DocCollection, always refetching if lazy. Equivalent to get(false)
+     * @return The collection state modeled in zookeeper
+     */
     public DocCollection get(){
+      return get(false);
+    }
+
+    /** Return the DocCollection
+     * @param allowCached Determines if cached value can be used.  Applies only to LazyCollectionRef.
+     * @return The collection state modeled in zookeeper
+     */
+    public DocCollection get(boolean allowCached) {
       gets.incrementAndGet();
       return coll;
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b212f2e9/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java b/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java
index f4e4d1a..dbda3d8 100644
--- a/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java
+++ b/solr/solrj/src/java/org/apache/solr/common/cloud/ZkStateReader.java
@@ -70,6 +70,7 @@ import static java.util.Collections.unmodifiableSet;
 import static org.apache.solr.common.util.Utils.fromJSON;
 
 public class ZkStateReader implements Closeable {
+  public static final int STATE_UPDATE_DELAY = Integer.getInteger("solr.OverseerStateUpdateDelay", 2000);  // delay between cloud state updates
   private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
   
   public static final String BASE_URL_PROP = "base_url";
@@ -136,7 +137,7 @@ public class ZkStateReader implements Closeable {
 
   public static final String SHARD_LEADERS_ZKNODE = "leaders";
   public static final String ELECTION_NODE = "election";
-  
+
   /** Collections tracked in the legacy (shared) state format, reflects the contents of clusterstate.json. */
   private Map<String, ClusterState.CollectionRef> legacyCollectionStates = emptyMap();
 
@@ -163,6 +164,8 @@ public class ZkStateReader implements Closeable {
 
   private final ExecutorService notifications = ExecutorUtil.newMDCAwareCachedThreadPool("watches");
 
+  private static final long LAZY_CACHE_TIME = TimeUnit.NANOSECONDS.convert(STATE_UPDATE_DELAY, TimeUnit.MILLISECONDS);
+
   /**
    * Get current {@link AutoScalingConfig}.
    * @return current configuration from <code>autoscaling.json</code>. NOTE:
@@ -632,19 +635,36 @@ public class ZkStateReader implements Closeable {
   }
 
   private class LazyCollectionRef extends ClusterState.CollectionRef {
-
     private final String collName;
+    private long lastUpdateTime;
+    private DocCollection cachedDocCollection;
 
     public LazyCollectionRef(String collName) {
       super(null);
       this.collName = collName;
+      this.lastUpdateTime = -1;
     }
 
     @Override
-    public DocCollection get() {
+    public synchronized DocCollection get(boolean allowCached) {
       gets.incrementAndGet();
-      // TODO: consider limited caching
-      return getCollectionLive(ZkStateReader.this, collName);
+      if (!allowCached || lastUpdateTime < 0 || System.nanoTime() - lastUpdateTime > LAZY_CACHE_TIME) {
+        boolean shouldFetch = true;
+        if (cachedDocCollection != null) {
+          Stat exists = null;
+          try {
+            exists = zkClient.exists(getCollectionPath(collName), null, true);
+          } catch (Exception e) {}
+          if (exists != null && exists.getVersion() == cachedDocCollection.getZNodeVersion()) {
+            shouldFetch = false;
+          }
+        }
+        if (shouldFetch) {
+          cachedDocCollection = getCollectionLive(ZkStateReader.this, collName);
+          lastUpdateTime = System.nanoTime();
+        }
+      }
+      return cachedDocCollection;
     }
 
     @Override