【发布时间】:2014-01-14 10:51:53
【问题描述】:
我有一个 Java Web 应用程序,它使用 Solrj API 对 Solr 4.4 中的数据进行索引,并使用其 HTTP API 直接查询 Solr。我的 webapp 和 Solr 都在同一台服务器上各自的 Tomcat 实例中运行。我刚刚将我的应用程序的 HttpSolrServer 从使用默认的 HttpClient 配置更改为使用使用 PoolingClientConnectionManager 的 SystemDefaultHttpClient 的自定义配置单例实例(Spring bean)。
我的问题是我的 Solr webapp 每隔几天就会抛出 OutOfMemoryExceptions。我可以通过netstat 和lsof 看到,在向 Solr 发出请求后,我的应用程序在 CLOSE_WAIT 状态下维护到 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 实例如下所示:
SolrServer ss = new HttpSolrServer("http://localhost:8100/solr/core1", httpClient);
我的 Solr HTTP 请求如下所示:
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();
}
【问题讨论】:
-
您查看过日志吗?那边有什么可疑的吗?
-
webapp 只是在查询还是它也发送文档以供索引?
-
Solr 日志中没有可疑内容。尝试使用“无法提交”消息提交时最常引发异常。我的网络应用程序既可以使用 Solrj 进行索引和查询,也可以通过 http api 进行查询。
标签: java solr apache-httpclient-4.x