Elasticsearch Java高级REST客户端建立一堆TCP连接,并且在放置数据后不关闭该连接

Sae*_*and 7 java elasticsearch

我有一个每秒运行一次的定期作业(这是可配置的)。

在这项工作中,我首先创建到Elasticsearch服务器的连接:

RestHighLevelClient client = new RestHighLevelClient(
                    RestClient.builder(new HttpHost(address, port, "http")));
Run Code Online (Sandbox Code Playgroud)

然后,我检查是否存在一个称为的特殊索引test。如果不存在,请先创建它。

GetIndexRequest indexRequest = new GetIndexRequest();
indexRequest.indices("test");
boolean testIndexIsExists = false;
try {

     testIndexIsExists = client.indices().exists(indexRequest, RequestOptions.DEFAULT);

    } catch (IOException ioe) {

    logger.error("Can't check the existence of test index in Elasticsearch!");

}
if(testIndexIsExists) {
     // bulk request...
} else {
    CreateIndexRequest testIndex = new CreateIndexRequest("test");

    try {

        testIndex.mapping("doc", mappingConfiguration);

        client.indices().create(testIndex, RequestOptions.DEFAULT);
        // bulk request...

    } catch (IOException ioe) {

        logger.error("Can't create test index in Elasticsearch");
    }

}
Run Code Online (Sandbox Code Playgroud)

在执行具有近2000个文档的批量请求后,我在此作业中关闭了连接:

client.close();
Run Code Online (Sandbox Code Playgroud)

Java高级REST客户端版本:

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>6.4.0</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

我的问题是一堆已经建立但尚未关闭的TCP连接。这些TCP连接会随时间占用所有操作系统TCP连接。

另一方面,我有点困惑。是否应RestHighLevelClient例如是单独的对象为整个应用程序或我必须创建在每一项工作做这项工作后,运行周期和关闭的情况下一个新的实例?

Mik*_*ike 9

高级客户端已经为您维护了一个连接池,因此我将其用作单例。不断地创建和关闭连接池代价高昂,而且客户端和底层 HTTP 连接池是线程安全的。此外,close()对客户端的调用只是委托给 Apache HTTP 客户端shutdown()方法,因此您受它们处理清理和释放资源的方式的支配。

如果您使用的是 Spring 或其他一些 DI 框架,则很容易创建可以根据需要注入的客户端的单例实例。您可以将调用添加到client.close()bean 关闭/销毁生命周期阶段的一部分。

使用 Spring Boot 的快速示例:

@Configuration
@ConditionalOnClass(RestHighLevelClient.class)
public class ElasticSearchConfiguration {

    @Value("${elasticsearch.address}")
    String address;

    @Value("${elasticsearch.port}")
    int port;

    @Bean(destroyMethod = "close")
    public RestHighLevelClient restHighLevelClient() {
        return new RestHighLevelClient(
                RestClient.builder(new HttpHost(address, port, "http")));
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:在这种情况下,Spring 会自动检测到 bean 有一个close方法,并在 bean 被销毁时为您调用它。其他框架可能要求您指定应如何处理关闭。