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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Elasticsearch Java高级REST客户端建立一堆TCP连接,并且在放入数据后不要关闭该连接相关的知识,希望对你有一定的参考价值。

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

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

RestHighLevelClient client = new RestHighLevelClient(
                    RestClient.builder(new HttpHost(address, port, "http")));

然后我检查是否存在一个名为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");
    


在做了一个接近2000文档的批量请求之后,我关闭了这个工作中的连接:

client.close();

Java高级REST客户端版本:

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>6.4.0</version>
</dependency>

我的问题是已建立并未关闭的一堆TCP连接。这些TCP连接随着时间的推移占用所有操作系统TCP连接。

另一方面,我有点困惑。 RestHighLevelClient实例应该是整个应用程序的单例对象还是我必须在每个作业运行周期中创建一个新实例并在完成该工作后关闭实例?

答案

高级客户端已经为您维护连接池,因此我将其用作单例。不断创建和关闭连接池的成本很高,客户端和底层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")));
    

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

另一答案

RestHighLevelClient通常应该是单身,除非你有充分的理由。例如,如果您的工作每小时而不是一分钟运行,那么创建新实例并在工作之后关闭它可能是有意义的。

如果您确定在所有情况下都在调用close()(例如,您没有错过任何例外),那么我的下一个猜测是弹性客户端中的错误。

看起来他们忘记在存在的调用中使用响应:https://github.com/elastic/elasticsearch/blob/v6.4.0/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java#L1419

你能不在没有exists电话的情况下进行测试吗?

以上是关于Elasticsearch Java高级REST客户端建立一堆TCP连接,并且在放入数据后不要关闭该连接的主要内容,如果未能解决你的问题,请参考以下文章

如何在Spring Data Elasticsearch 2.2.3中配置Rest高级客户端的套接字超时

elasticsearch高级查询api

elasticsearch-rest-high-level-client操作elasticsearch

elasticsearch-rest-high-level-client操作elasticsearch

elasticsearch-rest-high-level-client操作elasticsearch

elasticsearch-rest-high-level-client操作elasticsearch