
org.apache.solr.client.solrj.impl.LBHttpSolrServer Maven / Gradle / Ivy
The newest version!
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.solr.client.solrj.impl;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.solr.client.solrj.*;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.SolrException;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
/**
* LBHttpSolrServer or "LoadBalanced HttpSolrServer" is just a wrapper to CommonsHttpSolrServer. This is useful when you
* have multiple SolrServers and the requests need to be Load Balanced among them. This should NOT be used for
* indexing. Also see the wiki page.
*
* It offers automatic failover when a server goes down and it detects when the server comes back up.
*
* Load balancing is done using a simple roundrobin on the list of servers.
*
* If a request to a server fails by an IOException due to a connection timeout or read timeout then the host is taken
* off the list of live servers and moved to a 'dead server list' and the request is resent to the next live server.
* This process is continued till it tries all the live servers. If atleast one server is alive, the request succeeds,
* andif not it fails.
*
* SolrServer lbHttpSolrServer = new LBHttpSolrServer("http://host1:8080/solr/","http://host2:8080/solr","http://host2:8080/solr");
* //or if you wish to pass the HttpClient do as follows
* httpClient httpClient = new HttpClient();
* SolrServer lbHttpSolrServer = new LBHttpSolrServer(httpClient,"http://host1:8080/solr/","http://host2:8080/solr","http://host2:8080/solr");
*
* This detects if a dead server comes alive automatically. The check is done in fixed intervals in a dedicated thread.
* This interval can be set using {@link #setAliveCheckInterval} , the default is set to one minute.
*
* When to use this?
This can be used as a software load balancer when you do not wish to setup an external
* load balancer. The code is relatively new and the API is currently experimental. Alternatives to this code are to use
* a dedicated hardware load balancer or using Apache httpd with mod_proxy_balancer as a load balancer. See Load balancing on Wikipedia
*
* @version $Id: LBHttpSolrServer.java 823653 2009-10-09 18:27:13Z hossman $
* @since solr 1.4
*/
public class LBHttpSolrServer extends SolrServer {
private final CopyOnWriteArrayList aliveServers = new CopyOnWriteArrayList();
private final CopyOnWriteArrayList zombieServers = new CopyOnWriteArrayList();
private ScheduledExecutorService aliveCheckExecutor;
private HttpClient httpClient;
private final AtomicInteger counter = new AtomicInteger(-1);
private ReentrantLock checkLock = new ReentrantLock();
private static final SolrQuery solrQuery = new SolrQuery("*:*");
static {
solrQuery.setRows(0);
}
private static class ServerWrapper {
final CommonsHttpSolrServer solrServer;
// Used only by the thread in aliveCheckExecutor
long lastUsed, lastChecked;
int failedPings = 0;
public ServerWrapper(CommonsHttpSolrServer solrServer) {
this.solrServer = solrServer;
}
public String toString() {
return solrServer.getBaseURL();
}
}
public LBHttpSolrServer(String... solrServerUrls) throws MalformedURLException {
this(new HttpClient(new MultiThreadedHttpConnectionManager()), solrServerUrls);
}
public LBHttpSolrServer(HttpClient httpClient, String... solrServerUrl)
throws MalformedURLException {
this(httpClient, new BinaryResponseParser(), solrServerUrl);
}
public LBHttpSolrServer(HttpClient httpClient, ResponseParser parser, String... solrServerUrl)
throws MalformedURLException {
this.httpClient = httpClient;
for (String s : solrServerUrl) {
aliveServers.add(new ServerWrapper(new CommonsHttpSolrServer(s, httpClient, parser)));
}
}
public void addSolrServer(String server) throws MalformedURLException {
CommonsHttpSolrServer solrServer = new CommonsHttpSolrServer(server, httpClient);
checkLock.lock();
try {
aliveServers.add(new ServerWrapper(solrServer));
} finally {
checkLock.unlock();
}
}
public String removeSolrServer(String server) {
try {
server = new URL(server).toExternalForm();
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
if (server.endsWith("/")) {
server = server.substring(0, server.length() - 1);
}
this.checkLock.lock();
try {
for (ServerWrapper serverWrapper : aliveServers) {
if (serverWrapper.solrServer.getBaseURL().equals(server)) {
aliveServers.remove(serverWrapper);
return serverWrapper.solrServer.getBaseURL();
}
}
if (zombieServers.isEmpty()) return null;
for (ServerWrapper serverWrapper : zombieServers) {
if (serverWrapper.solrServer.getBaseURL().equals(server)) {
zombieServers.remove(serverWrapper);
return serverWrapper.solrServer.getBaseURL();
}
}
} finally {
checkLock.unlock();
}
return null;
}
public void setConnectionTimeout(int timeout) {
httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(timeout);
}
/**
* set connectionManagerTimeout on the HttpClient.*
*/
public void setConnectionManagerTimeout(int timeout) {
httpClient.getParams().setConnectionManagerTimeout(timeout);
}
/**
* set soTimeout (read timeout) on the underlying HttpConnectionManager. This is desirable for queries, but probably
* not for indexing.
*/
public void setSoTimeout(int timeout) {
httpClient.getParams().setSoTimeout(timeout);
}
/**
* Tries to query a live server. If no live servers are found it throws a SolrServerException. If the request failed
* due to IOException then the live server is moved to dead pool and the request is retried on another live server if
* available. If all live servers are exhausted then a SolrServerException is thrown.
*
* @param request the SolrRequest.
*
* @return response
*
* @throws SolrServerException
* @throws IOException
*/
public NamedList
© 2015 - 2025 Weber Informatics LLC | Privacy Policy