Java 具有自定义HttpClient连接的Solr OutOfMemoryException

Java 具有自定义HttpClient连接的Solr OutOfMemoryException,java,solr,apache-httpclient-4.x,Java,Solr,Apache Httpclient 4.x,我有一个Java web应用程序,它使用Solrj API对Solr 4.4中的数据进行索引,并使用其HTTP API直接查询Solr。我的webapp和Solr都在同一台服务器上各自的Tomcat实例中运行。我刚刚将应用程序的HttpSolrServer从使用默认的HttpClient配置更改为使用PoolgClientConnectionManager使用SystemDefaultHttpClient的自定义配置单例实例(SpringBean) 我的问题是,我的Solr webapp每隔几天

我有一个Java web应用程序,它使用Solrj API对Solr 4.4中的数据进行索引,并使用其HTTP API直接查询Solr。我的webapp和Solr都在同一台服务器上各自的Tomcat实例中运行。我刚刚将应用程序的HttpSolrServer从使用默认的
HttpClient
配置更改为使用PoolgClientConnectionManager使用SystemDefaultHttpClient的自定义配置单例实例(SpringBean)

我的问题是,我的Solr webapp每隔几天就会抛出很多内存异常。我可以通过
netstat
lsof
看到,在向Solr发出请求后,我的应用程序将套接字保持在关闭等待状态,这可能表明我没有正确释放空闲连接。然而,Solr进程似乎并没有从其末端保持任何套接字打开

我在这篇文章中的目标是确认或消除一种理论,即我对HttpClient API的滥用可能导致Solr中的内存问题。我认为这可能(也将)导致我的应用程序出现问题,但不会导致我连接的服务器出现问题

Solr在一夜之间抛出了这些异常,在我的应用程序大量使用之后,而不是在大量使用期间。如果这与挥之不去的联系无关,我不太确定下一步该去哪里寻找。Solr运行的Tomcat实例已经分配了3.5 GB的最大堆空间(-Xmx),因此我怀疑它是否需要更多。任何缩小我努力范围的帮助都将是巨大的

我的HttpClient实例如下所示:

SystemDefaultHttpClient httpClient = new SystemDefaultHttpClient();
httpClient.getCredentialsProvider().setCredentials(AuthScope.ANY,
    new UsernamePasswordCredentials("user", "password"));
PoolingClientConnectionManager cm = 
    (PoolingClientConnectionManager) httpClient.getConnectionManager();
cm.setMaxTotal(200);
HttpHost localhost = new HttpHost("localhost", 8100);
cm.setMaxPerRoute(new HttpRoute(localhost), 200);
SolrServer ss = new HttpSolrServer("http://localhost:8100/solr/core1", httpClient);
HttpPost httpPost = new HttpPost("http://localhost:8100/solr/core1/select");
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("q", "query terms"));
nvps.add(new BasicNameValuePair("fl", "field1,field2,field3"));
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
HttpResponse response = httpClient.execute(httpPost);

InputStream inputStream=null;
try {
    HttpEntity entity = response.getEntity();
    inputStream = entity.getContent();
    //do something with the response body
} finally {
    inputStream.close();
}
我的SolrServer实例如下所示:

SystemDefaultHttpClient httpClient = new SystemDefaultHttpClient();
httpClient.getCredentialsProvider().setCredentials(AuthScope.ANY,
    new UsernamePasswordCredentials("user", "password"));
PoolingClientConnectionManager cm = 
    (PoolingClientConnectionManager) httpClient.getConnectionManager();
cm.setMaxTotal(200);
HttpHost localhost = new HttpHost("localhost", 8100);
cm.setMaxPerRoute(new HttpRoute(localhost), 200);
SolrServer ss = new HttpSolrServer("http://localhost:8100/solr/core1", httpClient);
HttpPost httpPost = new HttpPost("http://localhost:8100/solr/core1/select");
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("q", "query terms"));
nvps.add(new BasicNameValuePair("fl", "field1,field2,field3"));
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
HttpResponse response = httpClient.execute(httpPost);

InputStream inputStream=null;
try {
    HttpEntity entity = response.getEntity();
    inputStream = entity.getContent();
    //do something with the response body
} finally {
    inputStream.close();
}
我的Solr HTTP请求如下所示:

SystemDefaultHttpClient httpClient = new SystemDefaultHttpClient();
httpClient.getCredentialsProvider().setCredentials(AuthScope.ANY,
    new UsernamePasswordCredentials("user", "password"));
PoolingClientConnectionManager cm = 
    (PoolingClientConnectionManager) httpClient.getConnectionManager();
cm.setMaxTotal(200);
HttpHost localhost = new HttpHost("localhost", 8100);
cm.setMaxPerRoute(new HttpRoute(localhost), 200);
SolrServer ss = new HttpSolrServer("http://localhost:8100/solr/core1", httpClient);
HttpPost httpPost = new HttpPost("http://localhost:8100/solr/core1/select");
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("q", "query terms"));
nvps.add(new BasicNameValuePair("fl", "field1,field2,field3"));
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
HttpResponse response = httpClient.execute(httpPost);

InputStream inputStream=null;
try {
    HttpEntity entity = response.getEntity();
    inputStream = entity.getContent();
    //do something with the response body
} finally {
    inputStream.close();
}
HttpPost-HttpPost=新的HttpPost(“http://localhost:8100/solr/core1/select");
List nvps=new ArrayList();
添加(新的BasicNameValuePair(“q”、“查询条件”);
添加(新的BasicNameValuePair(“fl”、“field1、field2、field3”);
setEntity(新的UrlEncodedFormEntity(nvps));
HttpResponse response=httpClient.execute(httpPost);
InputStream InputStream=null;
试一试{
HttpEntity=response.getEntity();
inputStream=entity.getContent();
//对反应体做些什么
}最后{
inputStream.close();
}

没有出现在您的特定场景中,但我的场景与您非常相似,您是否也接受了非法州豁免

请提供tomcat中的查询数、文档数、线程数 以及tomcat中的垃圾收集参数

您还可以尝试增加线程数来解决此问题

问候


Rajat

Solr中的OutOfMemoryErrors不是由我的应用程序中可能存在或不存在的任何连接管理缺陷引起的。我的问题似乎在Solr中的某个地方,关于合并段和/或垃圾收集,除了在不适当的测试服务器上使用高于平均水平之外

你看过日志了吗?那边有什么可疑的地方吗?这个webapp只是在询问,还是它也发送文档进行索引?Solr日志中没有可疑的地方。尝试使用“cannot commit”消息提交时,最常引发异常。我的web应用程序既使用Solrj进行索引和查询,也通过http api进行查询。我正在使用内存,但我认为我的GC参数是使用10个线程的并行GC。Solr在一个核心中有大约200000个文档,在第二个核心中有250万个文档,复制到第三个核心中进行查询。Solr的tomcat的最大线程设置为300,但我无法想象在我们的测试场景中一次有超过20或30个活动线程。我对查询的数量没有很好的猜测。我的测试场景涉及在Core1上进行索引和查询,而只在Core3上进行查询,Core3配置了大型缓存。