You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by sh...@apache.org on 2014/10/15 16:09:32 UTC
svn commit: r1632049 - in /lucene/dev/trunk/solr: ./
solrj/src/java/org/apache/solr/client/solrj/impl/
solrj/src/test/org/apache/solr/client/solrj/impl/
Author: shalin
Date: Wed Oct 15 14:09:31 2014
New Revision: 1632049
URL: http://svn.apache.org/r1632049
Log:
SOLR-4715: Add CloudSolrServer constructors which accept a HttpClient instance
Modified:
lucene/dev/trunk/solr/CHANGES.txt
lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrServer.java
lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrServer.java
lucene/dev/trunk/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrServerTest.java
Modified: lucene/dev/trunk/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/CHANGES.txt?rev=1632049&r1=1632048&r2=1632049&view=diff
==============================================================================
--- lucene/dev/trunk/solr/CHANGES.txt (original)
+++ lucene/dev/trunk/solr/CHANGES.txt Wed Oct 15 14:09:31 2014
@@ -169,6 +169,9 @@ New Features
* SOLR-6617: /update/json/docs path will use fully qualified node names by default
(NOble Paul)
+* SOLR-4715: Add CloudSolrServer constructors which accept a HttpClient instance.
+ (Hardik Upadhyay, Shawn Heisey, shalin)
+
Bug Fixes
----------------------
Modified: lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrServer.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrServer.java?rev=1632049&r1=1632048&r2=1632049&view=diff
==============================================================================
--- lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrServer.java (original)
+++ lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrServer.java Wed Oct 15 14:09:31 2014
@@ -96,6 +96,7 @@ public class CloudSolrServer extends Sol
private final LBHttpSolrServer lbServer;
private final boolean shutdownLBHttpSolrServer;
private HttpClient myClient;
+ private final boolean clientIsInternal;
//no of times collection state to be reloaded if stale state error is received
private static final int MAX_STALE_RETRIES = 5;
Random rand = new Random();
@@ -177,6 +178,7 @@ public class CloudSolrServer extends Sol
*/
public CloudSolrServer(String zkHost) {
this.zkHost = zkHost;
+ this.clientIsInternal = true;
this.myClient = HttpClientUtil.createClient(null);
this.lbServer = new LBHttpSolrServer(myClient);
this.lbServer.setRequestWriter(new BinaryRequestWriter());
@@ -184,7 +186,41 @@ public class CloudSolrServer extends Sol
this.updatesToLeaders = true;
shutdownLBHttpSolrServer = true;
lbServer.addQueryParams(STATE_VERSION);
+ }
+ /**
+ * Create a new client object that connects to Zookeeper and is always aware
+ * of the SolrCloud state. If there is a fully redundant Zookeeper quorum and
+ * SolrCloud has enough replicas for every shard in a collection, there is no
+ * single point of failure. Updates will be sent to shard leaders by default.
+ *
+ * @param zkHost
+ * The client endpoint of the zookeeper quorum containing the cloud
+ * state. The full specification for this string is one or more comma
+ * separated HOST:PORT values, followed by an optional chroot value
+ * that starts with a forward slash. Using a chroot allows multiple
+ * applications to coexist in one ensemble. For full details, see the
+ * Zookeeper documentation. Some examples:
+ * <p/>
+ * "host1:2181"
+ * <p/>
+ * "host1:2181,host2:2181,host3:2181/mysolrchroot"
+ * <p/>
+ * "zoo1.example.com:2181,zoo2.example.com:2181,zoo3.example.com:2181"
+ * @param httpClient
+ * the {@see HttpClient} instance to be used for all requests. The
+ * provided httpClient should use a multi-threaded connection manager.
+ */
+ public CloudSolrServer(String zkHost, HttpClient httpClient) {
+ this.zkHost = zkHost;
+ this.clientIsInternal = httpClient == null;
+ this.myClient = httpClient == null ? HttpClientUtil.createClient(null) : httpClient;
+ this.lbServer = new LBHttpSolrServer(myClient);
+ this.lbServer.setRequestWriter(new BinaryRequestWriter());
+ this.lbServer.setParser(new BinaryResponseParser());
+ this.updatesToLeaders = true;
+ shutdownLBHttpSolrServer = true;
+ lbServer.addQueryParams(STATE_VERSION);
}
/**
@@ -206,7 +242,31 @@ public class CloudSolrServer extends Sol
* @see #CloudSolrServer(String)
*/
public CloudSolrServer(Collection<String> zkHosts, String chroot) {
-
+ this(zkHosts, chroot, null);
+ }
+
+ /**
+ * Create a new client object using multiple string values in a Collection
+ * instead of a standard zkHost connection string. Note that this method will
+ * not be used if there is only one String argument - that will use
+ * {@link #CloudSolrServer(String)} instead.
+ *
+ * @param zkHosts
+ * A Java Collection (List, Set, etc) of HOST:PORT strings, one for
+ * each host in the zookeeper ensemble. Note that with certain
+ * Collection types like HashSet, the order of hosts in the final
+ * connect string may not be in the same order you added them.
+ * @param chroot
+ * A chroot value for zookeeper, starting with a forward slash. If no
+ * chroot is required, use null.
+ * @param httpClient
+ * the {@see HttpClient} instance to be used for all requests. The provided httpClient should use a
+ * multi-threaded connection manager.
+ * @throws IllegalArgumentException
+ * if the chroot value does not start with a forward slash.
+ * @see #CloudSolrServer(String)
+ */
+ public CloudSolrServer(Collection<String> zkHosts, String chroot, HttpClient httpClient) {
StringBuilder zkBuilder = new StringBuilder();
int lastIndexValue = zkHosts.size() - 1;
int i = 0;
@@ -225,12 +285,13 @@ public class CloudSolrServer extends Sol
"The chroot must start with a forward slash.");
}
}
-
+
/* Log the constructed connection string and then initialize. */
log.info("Final constructed zkHost string: " + zkBuilder.toString());
-
+
this.zkHost = zkBuilder.toString();
- this.myClient = HttpClientUtil.createClient(null);
+ this.clientIsInternal = httpClient == null;
+ this.myClient = httpClient == null ? HttpClientUtil.createClient(null) : httpClient;
this.lbServer = new LBHttpSolrServer(myClient);
this.lbServer.setRequestWriter(new BinaryRequestWriter());
this.lbServer.setParser(new BinaryResponseParser());
@@ -246,8 +307,23 @@ public class CloudSolrServer extends Sol
* @see #CloudSolrServer(String) for full description and details on zkHost
*/
public CloudSolrServer(String zkHost, boolean updatesToLeaders) {
+ this(zkHost, updatesToLeaders, null);
+ }
+
+ /**
+ * @param zkHost
+ * A zookeeper client endpoint.
+ * @param updatesToLeaders
+ * If true, sends updates only to shard leaders.
+ * @param httpClient
+ * the {@see HttpClient} instance to be used for all requests. The provided httpClient should use a
+ * multi-threaded connection manager.
+ * @see #CloudSolrServer(String) for full description and details on zkHost
+ */
+ public CloudSolrServer(String zkHost, boolean updatesToLeaders, HttpClient httpClient) {
this.zkHost = zkHost;
- this.myClient = HttpClientUtil.createClient(null);
+ this.clientIsInternal = httpClient == null;
+ this.myClient = httpClient == null ? HttpClientUtil.createClient(null) : httpClient;
this.lbServer = new LBHttpSolrServer(myClient);
this.lbServer.setRequestWriter(new BinaryRequestWriter());
this.lbServer.setParser(new BinaryResponseParser());
@@ -289,8 +365,8 @@ public class CloudSolrServer extends Sol
this.lbServer = lbServer;
this.updatesToLeaders = updatesToLeaders;
shutdownLBHttpSolrServer = false;
+ this.clientIsInternal = false;
lbServer.addQueryParams(STATE_VERSION);
-
}
public ResponseParser getParser() {
@@ -978,7 +1054,7 @@ public class CloudSolrServer extends Sol
lbServer.shutdown();
}
- if (myClient!=null) {
+ if (clientIsInternal && myClient!=null) {
myClient.getConnectionManager().shutdown();
}
Modified: lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrServer.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrServer.java?rev=1632049&r1=1632048&r2=1632049&view=diff
==============================================================================
--- lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrServer.java (original)
+++ lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrServer.java Wed Oct 15 14:09:31 2014
@@ -45,8 +45,9 @@ import java.util.*;
* Do <b>NOT</b> use this class for indexing in master/slave scenarios since documents must be sent to the
* correct master; no inter-node routing is done.
*
- * In SolrCloud (leader/replica) scenarios, this class may be used for updates since updates will be forwarded
- * to the appropriate leader.
+ * In SolrCloud (leader/replica) scenarios, it is usually better to use
+ * {@link org.apache.solr.client.solrj.impl.CloudSolrServer}, but this class may be used
+ * for updates because the server will forward them to the appropriate leader.
*
* Also see the <a href="http://wiki.apache.org/solr/LBHttpSolrServer">wiki</a> page.
*
@@ -631,6 +632,9 @@ public class LBHttpSolrServer extends So
};
}
+ /**
+ * Return the HttpClient this instance uses.
+ */
public HttpClient getHttpClient() {
return httpClient;
}
@@ -638,11 +642,29 @@ public class LBHttpSolrServer extends So
public ResponseParser getParser() {
return parser;
}
-
+
+ /**
+ * Changes the {@link ResponseParser} that will be used for the internal
+ * SolrServer objects. Throws an exception if used after internal server
+ * objects have been added, so if you want to use this method, you must
+ * not put any URLs in your constructor.
+ *
+ * @param parser Default Response Parser chosen to parse the response if the parser
+ * were not specified as part of the request.
+ * @see org.apache.solr.client.solrj.SolrRequest#getResponseParser()
+ */
public void setParser(ResponseParser parser) {
this.parser = parser;
}
-
+
+ /**
+ * Changes the {@link RequestWriter} that will be used for the internal
+ * SolrServer objects. Throws an exception if used after internal server
+ * objects have been added, so if you want to use this method, you must
+ * not put any URLs in your constructor.
+ *
+ * @param requestWriter Default RequestWriter, used to encode requests sent to the server.
+ */
public void setRequestWriter(RequestWriter requestWriter) {
this.requestWriter = requestWriter;
}
Modified: lucene/dev/trunk/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrServerTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrServerTest.java?rev=1632049&r1=1632048&r2=1632049&view=diff
==============================================================================
--- lucene/dev/trunk/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrServerTest.java (original)
+++ lucene/dev/trunk/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrServerTest.java Wed Oct 15 14:09:31 2014
@@ -32,6 +32,7 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
+import org.apache.http.client.HttpClient;
import org.apache.lucene.util.LuceneTestCase.Slow;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
@@ -122,6 +123,7 @@ public class CloudSolrServerTest extends
public void doTest() throws Exception {
allTests();
stateVersionParamTest();
+ customHttpClientTest();
}
private void allTests() throws Exception {
@@ -439,4 +441,20 @@ public class CloudSolrServerTest extends
// see SOLR-6146 - this test will fail by virtue of the zkClient tracking performed
// in the afterClass method of the base class
}
+
+ public void customHttpClientTest() {
+ CloudSolrServer server = null;
+ ModifiableSolrParams params = new ModifiableSolrParams();
+ params.set(HttpClientUtil.PROP_SO_TIMEOUT, 1000);
+ HttpClient client = null;
+
+ try {
+ client = HttpClientUtil.createClient(params);
+ server = new CloudSolrServer(zkServer.getZkAddress(), client);
+ assertTrue(server.getLbServer().getHttpClient() == client);
+ } finally {
+ server.shutdown();
+ client.getConnectionManager().shutdown();
+ }
+ }
}