【问题标题】:Elasticsearch: restart node after java.lang.OutOfMemoryError: Java heap spaceElasticsearch:java.lang.OutOfMemoryError 后重启节点:Java 堆空间
【发布时间】:2021-01-05 05:50:30
【问题描述】:

我的一个 ES 节点由于 java.lang.OutOfMemoryError: Java heap space 错误而失败。以下是日志中的完整堆栈跟踪:

    [2020-09-18T04:25:04,215][WARN ][o.e.a.b.TransportShardBulkAction] [search1] [[my_index_4][0]] failed to perform indices:data/write/bulk[s] on replica [my_index_4][0], node[cm_76wfGRFm9nbPR1mJxTQ], [R], s[STARTED], a[id=BUpviwHxQK2qC3GrELC2Hw]
org.elasticsearch.transport.NodeDisconnectedException: [search3][X.X.X.179:9300][indices:data/write/bulk[s][r]] disconnected
[2020-09-18T04:25:04,215][WARN ][o.e.c.a.s.ShardStateAction] [search1] [my_index_4][0] received shard failed for shard id [[my_index_4][0]], allocation id [BUpviwHxQK2qC3GrELC2Hw], primary term [2], message [failed to perform indices:data/write/bulk[s] on replica [my_index_4][0], node[cm_76wfGRFm9nbPR1mJxTQ], [R], s[STARTED], a[id=BUpviwHxQK2qC3GrELC2Hw]], failure [NodeDisconnectedException[[search3][X.X.X.179:9300][indices:data/write/bulk[s][r]] disconnected]]
org.elasticsearch.transport.NodeDisconnectedException: [search3][X.X.X.179:9300][indices:data/write/bulk[s][r]] disconnected
[2020-09-18T04:25:04,215][DEBUG][o.e.a.a.c.n.i.TransportNodesInfoAction] [search1] failed to execute on node [cm_76wfGRFm9nbPR1mJxTQ]
org.elasticsearch.transport.NodeDisconnectedException: [search3][X.X.X.179:9300][cluster:monitor/nodes/info[n]] disconnected
[2020-09-18T04:25:04,219][INFO ][o.e.c.r.a.AllocationService] [search1] Cluster health status changed from [GREEN] to [YELLOW] (reason: [shards failed [[my_index_4][0]] ...]).
[2020-09-18T04:25:05,450][INFO ][o.e.m.j.JvmGcMonitorService] [search1] [gc][11099506] overhead, spent [605ms] collecting in the last [1.4s]
[2020-09-18T04:25:05,453][ERROR][o.e.b.ElasticsearchUncaughtExceptionHandler] [search1] fatal error in thread [elasticsearch[search1][search][T#5]], exiting
java.lang.OutOfMemoryError: Java heap space
at org.elasticsearch.search.aggregations.bucket.composite.CompositeValuesSource$GlobalOrdinalValuesSource.<init>(CompositeValuesSource.java:137) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.search.aggregations.bucket.composite.CompositeValuesSource.wrapGlobalOrdinals(CompositeValuesSource.java:123) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.search.aggregations.bucket.composite.CompositeValuesComparator.<init>(CompositeValuesComparator.java:50) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.search.aggregations.bucket.composite.CompositeAggregator.<init>(CompositeAggregator.java:69) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.search.aggregations.bucket.composite.CompositeAggregationFactory.createInternal(CompositeAggregationFactory.java:52) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.search.aggregations.AggregatorFactory.create(AggregatorFactory.java:216) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.search.aggregations.AggregatorFactories.createTopLevelAggregators(AggregatorFactories.java:216) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.search.aggregations.AggregationPhase.preProcess(AggregationPhase.java:55) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.search.query.QueryPhase.execute(QueryPhase.java:105) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.indices.IndicesService.lambda$loadIntoContext$14(IndicesService.java:1133) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.indices.IndicesService$$Lambda$2241/341562582.accept(Unknown Source) ~[?:?]
at org.elasticsearch.indices.IndicesService.lambda$cacheShardLevelResult$15(IndicesService.java:1186) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.indices.IndicesService$$Lambda$2242/1286052129.get(Unknown Source) ~[?:?]
at org.elasticsearch.indices.IndicesRequestCache$Loader.load(IndicesRequestCache.java:160) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.indices.IndicesRequestCache$Loader.load(IndicesRequestCache.java:143) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.common.cache.Cache.computeIfAbsent(Cache.java:412) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.indices.IndicesRequestCache.getOrCompute(IndicesRequestCache.java:116) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.indices.IndicesService.cacheShardLevelResult(IndicesService.java:1192) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.indices.IndicesService.loadIntoContext(IndicesService.java:1132) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.search.SearchService.loadOrExecuteQueryPhase(SearchService.java:305) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.search.SearchService.executeQueryPhase(SearchService.java:340) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.search.SearchService$2.onResponse(SearchService.java:316) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.search.SearchService$2.onResponse(SearchService.java:312) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.search.SearchService$3.doRun(SearchService.java:1002) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:672) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.common.util.concurrent.TimedRunnable.doRun(TimedRunnable.java:41) ~[elasticsearch-6.2.4.jar:6.2.4]
at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37) ~[elasticsearch-6.2.4.jar:6.2.4]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_171]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_171]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_171]

由于上述异常,当我访问任何 ES API 时,我都会收到 master_not_discovered_exception

问题:谁能告诉我接下来应该执行哪些步骤以使 Elasticsearch 恢复正常状态?有没有办法重启断开的节点?

【问题讨论】:

  • 这个错误意味着无论进程 - 现在已经死了(我对 cassandra 不是很熟悉),所以看来你需要重新启动这个进程?

标签: java elasticsearch elastic-stack elasticsearch-5


【解决方案1】:

首先让我简要解释一下可能导致此问题的原因:

  1. 如日志中所述,您似乎正在运行昂贵的聚合,这些聚合通常是内存密集型并且已知会消耗大量内存,您的垃圾收集 (GC) 无法回收这些内存,最终您的应用程序 ( ES) 内存不足并被杀死。
  2. 除了日志中显示的高成本聚合外,大量搜索和索引请求也可能导致高内存消耗,因此请查看此节点的搜索和索引慢日志,refer ES slow logs for more info

现在来解决部分

此 ES 节点已死,导致 master_not_discovered_exception 因此重新启动此节点并查看此异常是否消失非常重要。

防止OOM异常

  1. 你应该正确地configure the circuit breaker available in ES,如果可能的话升级到ES 7.X which has better circuit breakers based on real-memory
  2. 提高 ES 索引和搜索性能。

【讨论】:

  • 感谢您的回答。事实上,我在玩复合聚合大小参数。我将其值设置为Integer.MAX_VALUE,根据堆栈跟踪,在初始化 agg 值数组this.values = new long[size]; 时引发异常,这里的size 参数取自查询
  • @I.Domshchikov 很高兴听到我的回答很有帮助,我在您的回答中看到您提到了下一步并等待您的更新
  • 你的QQ,与我的应用程序导致的高负载下的ES可用性有关。我的 ES 堆设置是 -Xms1g -Xmx1g。我的应用程序使用复合查询来获取唯一的过滤器值,以允许用户过滤Foo 实体(按城市、名称...)。通常,有 3 个过滤器可用,因此应用程序并行发送 3 个复合查询以获取唯一值。对于每个过滤器,我想检索其所有唯一值,并且因为我不知道它们中有多少预先存在,所以我将size 参数设置为等于Foo 实体计数(7-10k)。你觉得我可能会再次面对OutOfMemoryError吗?
  • @I.Domshchikov ES 的 1GB 堆确实少了,您想将它用于聚合,而巨大的参数会导致更多的内存消耗,因此您可能会再次遇到 OOM 错误
【解决方案2】:

java.lang.OutOfMemoryError: Java heap space 是由运行复合聚合查询引起的,我将其 size 参数设置为 Integer.MAX_VALUE

{
    "size": 0,

    "aggregations": {
        "myParam.keyword": {
            "composite": {
                "size": 2147483647,
                "sources": [
                    {
                        "myParam.keyword": {
                            "terms": {
                                "field": "myParam.keyword",
                                "order": "asc"
                            }
                        }
                    }
                ]
            }
        }
    }
} 

根据堆栈跟踪,在初始化聚合值数组CompositeValuesSource.java:137时发生错误:

GlobalOrdinalValuesSource(ValuesSource.Bytes.WithOrdinals vs, int size, int reverseMul) {
    super(vs, size, reverseMul);
    this.values = new long[size];
}

这里,size 参数来自查询。

答案https://stackoverflow.com/a/63965634/5284890确认了根本原因。

我的下一步是使用以下命令再次停止并运行 Elasticsearch

sudo systemctl stop elasticsearch.service
sudo systemctl start elasticsearch.service

我的以下步骤将是检查此答案https://stackoverflow.com/a/63965634/5284890 中提到的 ES 文章中建议的断路器。

【讨论】:

  • @OpsterElasticsearchNinja,现在正在处理它。我将堆大小增加到 3Gb,还重构了构建复合聚合查询的应用程序逻辑以使用分页 (elastic.co/guide/en/elasticsearch/reference/current/…) - 旨在涵盖我不知道要提前返回的元素数量的情况。
  • 如果您需要更多信息,祝您好运和 lmk,如果我的回答对 TIA 有帮助,请不要忘记投票并接受 :)
  • @OpsterElasticsearchNinja,抱歉延迟回答。到目前为止,我们只做了 ES 集群的升级。我们有 3 个节点。每个节点 jvm 堆增加到 16GB。我们遵循这条规则来增加它@9​​87654324@。之后执行负载测试,集群能够处理所需的负载。虽然,我们还没有更新 ES,但决定稍后再做。一旦完成,我将研究断路器的东西。感谢您为解决此问题提供的帮助和支持。
  • 别担心,很高兴收到您的回复 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-14
  • 2021-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-13
  • 2016-01-21
相关资源
最近更新 更多