Elasticsearch Java High-Level REST Client 建立一堆 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 个文档的批量请求后,我关闭了 Elasticsearch 客户端连接:


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是整个应用程序的单例对象,还是我必须在每个作业运行周期中创建一个新实例并在完成该作业后关闭该实例?


RISEBY
浏览 233回答 2
2回答

达令说

高级客户端已经为您维护了一个连接池,所以我会将它用作单例。不断创建和关闭连接池的成本很高,而且客户端和底层 HTTP 连接池都是线程安全的。此外,对客户端的调用close()只是委托给 Apache HTTP 客户端shutdown()方法,因此您将受制于它们如何处理清理和释放资源。如果您使用 Spring 或其他一些 DI 框架,则可以轻松创建可以根据需要注入的客户端单例实例。您可以将调用添加client.close()为 bean 关闭/销毁生命周期阶段的一部分。使用 Spring Boot 的快速示例:@Configuration@ConditionalOnClass(RestHighLevelClient.class)public class ElasticSearchConfiguration {&nbsp; &nbsp; @Value("${elasticsearch.address}")&nbsp; &nbsp; String address;&nbsp; &nbsp; @Value("${elasticsearch.port}")&nbsp; &nbsp; int port;&nbsp; &nbsp; @Bean(destroyMethod = "close")&nbsp; &nbsp; public RestHighLevelClient restHighLevelClient() {&nbsp; &nbsp; &nbsp; &nbsp; return new RestHighLevelClient(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RestClient.builder(new HttpHost(address, port, "http")));&nbsp; &nbsp; }}注意:在这种情况下,Spring 会自动检测 bean 有一个close方法,并在 bean 被销毁时为您调用它。其他框架可能要求您指定应如何处理关闭。

回首忆惘然

RestHighLevelClient通常应该是单例的,除非你有充分的理由。例如,如果您的作业每小时而不是一分钟运行,那么创建新实例并在作业后关闭它可能是有意义的。如果您确定close()在所有情况下都在调用(例如,您没有错过任何异常),那么我的下一个猜测是弹性客户端中的错误。看起来他们忘记在 exists 调用中使用响应:&nbsp;https ://github.com/elastic/elasticsearch/blob/v6.4.0/client/rest-high-level/src/main/java/org/elasticsearch&nbsp;/client/RestHighLevelClient.java#L1419你能在没有exists电话的情况下进行测试吗?
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java