Be Sure to Reuse SolrServer and Apache HttpClient Instance

The Problem
In one solr-related application, we use SolrJ HttpSolrServer to push data into remote Solr server. In one load testing machine, we see SocketConnection Exception intermittently in remote Solr Server. 
Caused by: org.apache.solr.client.solrj.SolrServerException: java.net.SocketException: Connection reset
at org.apache.solr.client.solrj.impl.HttpSolrServer.request (HttpSolrServer.java:340)
Although for each request, we will retry several times. But we are still wondering what caused this exception and the network usage in the remote Solr server.
Use TCPView in Windows to Monitor Network
In linux, we can use lsof -i -p pid to list all port a process opens. In Windows, we can use TCPView
from Windows Sysinternals to monitor tcp connections. 

We see there are a thousands of connections in TIME_WAIT, CLOSE_WAIT, FIN_WAIT2 status in client and remote Solr server. This looks suspicious.
HttpSolrServer Usage Pattern
As the main logic in client is to use HttpSolrServer to send requests to Solr server. So we suspect there is something wrong when use HttpSolrServer.
Checked the code, the client program uses java Threadpool to send request, in each thread, it creates a HttpSolrServer, send a requests, then shutdown the SolServer.

Looked at wike page in SolrJ
HttpSolrServer is thread-safe and if you are using the following constructor, you *MUST* re-use the same instance for all requests.  If instances are created on the fly, it can cause a connection leak. The recommended practice is to keep a static instance of HttpSolrServer per solr server url and share it for all requests.

We changed the code to use a global static HttpSolrServer instance. Then use TCPView to monitor network usage after the change. Now there are only less than 20 connections open. 

Same logic applies when we use Apache HttpClient: Use one single HttpClient instance for each remote host.
Lesson Learned
Use tools in Windows Sysinternals and TCPView 
Reuse HttpSolrServer and Apache HttpClient instance.
Test Program
If you run the following test program, and monitor with TCPView, you can immediately notice the difference.
@Test
public void correctUsageSolrServer() throws InterruptedException {
 final String baseURL = "SOLRURL";
 final HttpSolrServer solrServer = new HttpSolrServer(baseURL);
 
 int i = 0;
 while (i++ < 1000) {
  Thread thread = new Thread() {
   @Override
   public void run() {
    SolrQuery query = new SolrQuery("*:*");
    try {
     QueryResponse rsp = solrServer.query(query);
     System.out.println(rsp);
    } catch (Exception e) {
     e.printStackTrace();
     throw new RuntimeException(e);
    }
   }
  };
  
  thread.start();
  Thread.sleep(10);
 }
 // be sure to shutdown solrServer at the end.
 solrServer.shutdown();
}

@Test
public void wrongUsageSolrServer() throws InterruptedException {
 final String baseURL = "SOLRURL";
 
 int i = 0;
 while (i++ < 1000) {
  Thread thread = new Thread() {
   @Override
   public void run() {
    final HttpSolrServer solrServer = new HttpSolrServer(baseURL);
    
    SolrQuery query = new SolrQuery("*:*");
    try {
     QueryResponse rsp = solrServer.query(query);
     System.out.println(rsp);
    } catch (Exception e) {
     e.printStackTrace();
     throw new RuntimeException(e);
    } finally {
     solrServer.shutdown();
    }
   }
  };
  
  thread.start();
  Thread.sleep(10);
 }
}
Resources
SolrJ Wiki
Connection Close in HttpClient
HttpClient Connection Management FAQ and Explanation of TIME_WAIT status
TCP Connection Termination Order
Post a Comment

Labels

Java (159) Lucene-Solr (112) Interview (61) All (58) J2SE (53) Algorithm (45) Soft Skills (38) Eclipse (33) Code Example (31) Linux (25) JavaScript (23) Spring (22) Windows (22) Web Development (20) Tools (19) Nutch2 (18) Bugs (17) Debug (16) Defects (14) Text Mining (14) J2EE (13) Network (13) Troubleshooting (13) PowerShell (11) Chrome (9) Design (9) How to (9) Learning code (9) Performance (9) Problem Solving (9) UIMA (9) html (9) Http Client (8) Maven (8) Security (8) bat (8) blogger (8) Big Data (7) Continuous Integration (7) Google (7) Guava (7) JSON (7) Shell (7) ANT (6) Coding Skills (6) Database (6) Lesson Learned (6) Programmer Skills (6) Scala (6) Tips (6) css (6) Algorithm Series (5) Cache (5) Dynamic Languages (5) IDE (5) System Design (5) adsense (5) xml (5) AIX (4) Code Quality (4) GAE (4) Git (4) Good Programming Practices (4) Jackson (4) Memory Usage (4) Miscs (4) OpenNLP (4) Project Managment (4) Spark (4) Testing (4) ads (4) regular-expression (4) Android (3) Apache Spark (3) Become a Better You (3) Concurrency (3) Eclipse RCP (3) English (3) Happy Hacking (3) IBM (3) J2SE Knowledge Series (3) JAX-RS (3) Jetty (3) Restful Web Service (3) Script (3) regex (3) seo (3) .Net (2) Android Studio (2) Apache (2) Apache Procrun (2) Architecture (2) Batch (2) Bit Operation (2) Build (2) Building Scalable Web Sites (2) C# (2) C/C++ (2) CSV (2) Career (2) Cassandra (2) Distributed (2) Fiddler (2) Firefox (2) Google Drive (2) Gson (2) How to Interview (2) Html Parser (2) Http (2) Image Tools (2) JQuery (2) Jersey (2) LDAP (2) Life (2) Logging (2) Python (2) Software Issues (2) Storage (2) Text Search (2) xml parser (2) AOP (1) Application Design (1) AspectJ (1) Chrome DevTools (1) Cloud (1) Codility (1) Data Mining (1) Data Structure (1) ExceptionUtils (1) Exif (1) Feature Request (1) FindBugs (1) Greasemonkey (1) HTML5 (1) Httpd (1) I18N (1) IBM Java Thread Dump Analyzer (1) JDK Source Code (1) JDK8 (1) JMX (1) Lazy Developer (1) Mac (1) Machine Learning (1) Mobile (1) My Plan for 2010 (1) Netbeans (1) Notes (1) Operating System (1) Perl (1) Problems (1) Product Architecture (1) Programming Life (1) Quality (1) Redhat (1) Redis (1) Review (1) RxJava (1) Solutions logs (1) Team Management (1) Thread Dump Analyzer (1) Visualization (1) boilerpipe (1) htm (1) ongoing (1) procrun (1) rss (1)

Popular Posts