我们使用elasticsearch REST Java客户端(我们在Java 7中,因此无法使用普通的elasticsearch Java客户端)与我们的elasticsearch服务器进行交互。除了当我们试图对大约130万个文档进行初始索引时,这一切都可以正常工作。这将运行了一段时间,但我们已经看到了弹性搜索的OutOfMemoryError REST Java客户端通过apache http nio
20/06 21:27:33,153 ERROR [cid=51][stderr][write:71] (pool-837116-thread-1) Exception in thread "pool-837116-thread-1" java.lang.OutOfMemoryError: unable to create new native thread
20/06 21:27:33,154 ERROR [cid=51][stderr][write:71] (pool-837116-thread-1) at java.lang.Thread.start0(Native Method)
20/06 21:27:33,154 ERROR [cid=51][stderr][write:71] (pool-837116-thread-1) at java.lang.Thread.start(Thread.java:693)
20/06 21:27:33,154 ERROR [cid=51][stderr][write:71] (pool-837116-thread-1) at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor.execute(AbstractMultiworkerIOReactor.java:334)
20/06 21:27:33,154 ERROR [cid=51][stderr][write:71] (pool-837116-thread-1) at org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager.execute(PoolingNHttpClientConnectionManager.java:194)
20/06 21:27:33,154 ERROR [cid=51][stderr][write:71] (pool-837116-thread-1) at org.apache.http.impl.nio.client.CloseableHttpAsyncClientBase$1.run(CloseableHttpAsyncClientBase.java:64)
20/06 21:27:33,155 ERROR [cid=51][stderr][write:71] (pool-837116-thread-1) at java.lang.Thread.run(Thread.java:724)
跟在后面几十万的文件被
java.lang.IllegalStateException: Request cannot be executed; I/O reactor status: STOPPED
at org.apache.http.util.Asserts.check(Asserts.java:46)
at org.apache.http.impl.nio.client.CloseableHttpAsyncClientBase.ensureRunning(CloseableHttpAsyncClientBase.java:90)
at org.apache.http.impl.nio.client.InternalHttpAsyncClient.execute(InternalHttpAsyncClient.java:123)
at org.elasticsearch.client.RestClient.performRequestAsync(RestClient.java:343)
at org.elasticsearch.client.RestClient.performRequestAsync(RestClient.java:325)
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:218)
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:191)
正如你可以看到Elasticsearch REST客户端使用的Apache HTTP NIO。我发现奇怪的是,nio库正在为每个请求(或连接?)创建一个线程。从上面的日志可以看到线程(pool-837116-thread-1)。还有很多I/O调度程序线程数量越来越多。
虽然活动线程的总数似乎没有太大变化。 因此,似乎并非重复使用线程(或实际上是)为每个连接周期创建新线程。 上传基本上是: 1.创建客户
restClient = RestClient.builder(new HttpHost(host.getHost(),host.getPort(),host.getProtocol())/*,new HttpHost(host.getHost(),host.getPort()+1,host.getProtocol())*/)
.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
return httpClientBuilder
.setDefaultCredentialsProvider(credsProvider)
}
}).setMaxRetryTimeoutMillis(30000).build();
- 使用JSON体和靠近客户
尝试{ HttpEntity实体=新NStringEntity(JSON
发送请求,ContentType.APPLICATION_JSON); 响应indexResponse = restClient.performRequest(“PUT”,endpoint,parameters,entity,header); log.debug(“Response#0#1”,indexResponse,indexResponse.getStatusLine()); log.debug(“Entity#0”,indexResponse.getEntity());
}finally{ if(restClient!=null){ log.debug("Closing restClient #0", restClient); restClient.close(); } }
这是正常的吗?为什么不是apache nio重用线程?这是弹性搜索REST客户端,apache nio或我的代码的问题吗?我打电话给restClient,不知道我该怎么做。
我试图设置线程数减少到1个在IO反应堆:
restClient = RestClient.builder(new HttpHost(host.getHost(),host.getPort(),host.getProtocol())/*,new HttpHost(host.getHost(),host.getPort()+1,host.getProtocol())*/)
.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
return httpClientBuilder
.setDefaultCredentialsProvider(credsProvider)
.setDefaultIOReactorConfig(IOReactorConfig.custom().setIoThreadCount(1).build()); //set to one thread
}
}).setMaxRetryTimeoutMillis(30000).build();
但对于线程的重用并没有改变任何东西。
您是使用批量插入还是逐一插入? – jvwilge
我找到了OutOfMemoryError的原因。虽然我正在使用try - finally块来关闭客户端,但在该块之外抛出一个异常(块没有涵盖所有的东西哦)。但看起来错误的是创建了这么多的线程(虽然整个线程的数量并没有显着增加)。 – Ben
这是一个一个插入,因为我需要确保上传每个数据。它使用与正常索引相同的机制。 – Ben