当前位置: 首页 > 知识库问答 >
问题:

Elasticsearch Java高级REST客户端建立一组TCP连接,并在索引数据后不关闭它们

唐康安
2023-03-14

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

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

共有2个答案

长孙章横
2023-03-14

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

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

看起来他们忘记了使用exists调用中的响应:https://html" target="_blank">github.com/elastic/elasticsearch/blob/v6.4.0/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java#L1419

您是否能够在没有调用exists的情况下进行测试?

马泓
2023-03-14

高级客户端已经为您维护了一个连接池,所以我将它作为一个单例使用。不断创建和关闭连接池代价高昂,而且客户端和底层HTTP连接池是线程安全的。此外,在客户端上调用HTTP客户端的close()只会委托给apachehttp客户端的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有一个关闭方法,并在bean被销毁时为您调用它。其他框架可能要求您指定应该如何处理关闭。

 类似资料:
  • 我们不允许寻求书籍、工具、软件库等推荐的问题。你可以编辑这个问题,以便用事实和引用来回答。 我是弹性搜索的初学者,正在寻找将弹性搜索与Spring boot相结合的最佳方式。 我不确定使用以下哪一项:- > Spring数据弹性搜索 开玩笑 谢谢

  • 我正在使用java高级rest客户端在我的应用程序中集成elasticsearch,但无法创建索引 在某个地方,我发现要执行请求,我们需要使用index(请求)方法(我在代码中已注释),但它表明index(请求)方法已从RestHighLevelClient类型中弃用。 这是我的代码:

  • 在Mac OS X 10.8机器上,我有一台Tomcat 7.0.40服务器和一台客户端,都在本地运行。通过三方握手建立TCP连接,然后立即从服务器发送FIN、ACK和RST。客户端收到“来自服务器的文件结束”或“连接重置”。 TCP序列: 客户端SYN 服务器SYN,确认 客户端确认 服务器[TCP窗口更新]确认字符 服务器FIN,确认字符 客户端确认字符 服务器[TCP Dup确认字符]确认字

  • socket.io 0.9 node.js 0.10.15 速递3.3.4 即:调用 --服务器端 --客户端

  • 问题内容: 如何关闭客户端的套接字连接? 我在用: socket.io 0.9 node.js 0.10.15 express3.3.4 即:呼叫 -服务器端 - 客户端 如果加载测试页,则需要来自服务器的一些值(getInitData)。 在第一页上,我获取一次数据,在重新加载或第二遍上,我获取两次数据,依此类推。 重新加载页面以及离开页面后,服务器端的连接将自动关闭。 但是在客户端,连接仍然打

  • 我刚刚开始使用hazelcast[3.3.1]。根据hazelcast应用程序和客户端教程,我创建了一个hazelcast应用程序实例和一个客户端(使用eclipse IDE)。 从客户端,我能够将对象添加到地图并成功获取它们。但是,我在实例的控制台上看到以下警告,它们似乎警告客户端断开连接。这是每个客户端get/put的正常行为吗? 在退出客户端程序之前,是否有适当的方法断开客户端与实例的连接?