【问题标题】:Are there memory leaks in ElasticSearch's TransportClient 5.4.3 or is my code flawed?ElasticSearch 的 TransportClient 5.4.3 中是否存在内存泄漏或我的代码有缺陷?
【发布时间】:2017-07-05 21:27:22
【问题描述】:

ElasticSearch 的 TransportClient 5.4.3 中是否存在内存泄漏?还是我没有正确使用和关闭对象?

我在 JRE 1.8.0_66 上的 Jenkins (2.68) 中使用客户端,并在 Groovy 中编写我的代码。 BulkRequestBuilder 用于提交多条记录。

在整个代码中,这些 4x 16 MB 字节数组出现在内存中,但即使通过 TransportClient.close() 方法也不会关闭: 如果我更慢地单步执行代码,我可以得到这些 16 MB 字节数组中的 9 倍,其中一些看起来非常相似:

我相信我完全遵循官方文档:https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html

这是我正在使用的代码的精简版:

@Grapes([
    @Grab(group = "org.apache.logging.log4j", module = "log4j-api", version = "2.8.2", initClass = true),
    @Grab(group = "org.apache.logging.log4j", module = "log4j-core", version = "2.8.2", initClass = true),
    @Grab(group = "org.elasticsearch.client", module = "transport", version = "5.4.3", initClass = true)
])
public class ElasticSearchReport implements Serializable {

    pubblic void execute() {
        // Data to report.
        List<Map<String, Object>> data = ...

        // ElasticSearch settings. Do not use sniffing because we want to upload data to the master node.
        Settings settings = Settings.builder()
            .put("cluster.name", "my-cluster")
            .put("client.transport.sniff", false)
            .build()

        PreBuiltTransportClient preBuiltTransportClient = new PreBuiltTransportClient(settings)
        TransportClient client = preBuiltTransportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("my-elastic-search-host"), 9300))
        List<String> errors = new LinkedList<String>()

        try {
            BulkRequestBuilder bulkRequest = client.prepareBulk()

            // Build the bulk query with each data entry.
            data.each({entry ->
                String serialisedEntry = SerializationUtils.toJson(entry)
                bulkRequest.add(client.prepareIndex("my-index", "my-type").setSource(serialisedEntry, XContentType.JSON))
            })

            // Process the response.
            bulkRequest.get().getItems().each({response ->
                if (response.failed) {
                    errors.add(response.failure.message)
                    return
                }

                final String statusName = response.status().name()

                // Check statusName ...
            })

            if (errors) throw new Exception(...)
        } finally {
            client.close()
            preBuiltTransportClient.close()
        }
    }
}

从我正在使用的对象中,只有 PreBuiltTransportClientTransportClient 实现了 Closeable,所以我试图在我的 finally 块中明确地关闭它们。

尝试使用.withCloseable()(Groovy 相当于try-with-resources),但它并没有阻止问题的发生。

我想也许我的bulkRequest.get().getItems().each({response -&gt; 行做了一些有趣的事情,所以我用以下内容替换了它,但没有效果:

BulkResponse bulkResponse = bulkRequest.get()
BulkItemResponse[] bulkItemResponses = bulkResponse.getItems()
for (int responseIndex = 0; responseIndex < bulkItemResponses.length; responseIndex++) { ... }

我也尝试用BulkResponse bulkResponse = bulkRequest.execute().actionGet() 替换BulkResponse bulkResponse = bulkRequest.get(),但没有成功。

【问题讨论】:

    标签: java elasticsearch memory groovy memory-leaks


    【解决方案1】:

    ElasticSearch Java REST Client 似乎没有这些问题。 我已经切换到它并且没有遇到内存不足错误。一旦客户端关闭并限定范围,所有相对较大的字节数组都会被释放。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多