【问题标题】:ElasticSearch's MasterService taking too long to compute cluster state and throw ProcessClusterEventTimeoutExceptionElasticSearch 的 MasterService 计算集群状态并抛出 ProcessClusterEventTimeoutException 的时间过长
【发布时间】:2020-03-04 02:29:13
【问题描述】:

我们有一个应用程序每秒向我们的 ES 集群添加数千个文档。每次我们滚动我们正在写入的索引并开始写入新索引时,我们都会收到以下错误,这些错误不允许在大约 1 分钟内提取文档。 1 分钟后,一切恢复正常,直到我们再次翻转索引。

[WARN ][o.e.c.s.MasterService    ] [NODE_NAME_1] took [28.3s], which is over [10s], to compute cluster state update for [put-mapping[_doc, _doc, ...
[DEBUG][o.e.a.a.i.m.p.TransportPutMappingAction] [NODE_NAME_1] failed to put mappings on indices [[[INDEX_1/SOME_ID]]], type [_doc]
org.elasticsearch.cluster.metadata.ProcessClusterEventTimeoutException: failed to process cluster event (put-mapping) within 30s
    at org.elasticsearch.cluster.service.MasterService$Batcher.lambda$onTimeout$0(MasterService.java:143) [elasticsearch-7.5.2.jar:7.5.2]
    at java.util.ArrayList.forEach(ArrayList.java:1507) [?:?]
    at org.elasticsearch.cluster.service.MasterService$Batcher.lambda$onTimeout$1(MasterService.java:142) [elasticsearch-7.5.2.jar:7.5.2]
    at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingRunnable.run(ThreadContext.java:703) [elasticsearch-7.5.2.jar:7.5.2]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
    at java.lang.Thread.run(Thread.java:830) [?:?]

在第一行中,我将省略号放在末尾,因为它实际上很大,这里是我们所看到的图像(正如您在图像中看到的那样,该行突然结束):

你知道那些错误信息是关于什么的吗?

是否有可能因为我们的集群状态太大而看到这些消息?这是否意味着我们有太多的分片或节点?

谢谢。

注意:

  • 我们使用 ElasticSearch 7.5.2
  • 我们不使用 ILM,当我说“翻转我们的索引”时,我们所做的是开始写入我们几小时前创建但未使用的新索引。然后我们停止写入旧索引。

【问题讨论】:

  • 你有多少分片?
  • 我们有大约 30.000 个分片
  • @MondKin,30k 分片在 1 个 ES 节点上,或者在集群中,你的数据节点的堆大小是多少?您的集群中有多少个节点?
  • 我们总共有 60 个数据节点,在热温架构中,一些节点有 32GiB 堆,而另一些节点有 16GiB。
  • @MondKin,顺便说一句,很棒的核心 ES 内部问题,喜欢它

标签: elasticsearch


【解决方案1】:

当 ES 无法应对大型集群状态时会出现此错误,并且更新集群状态的默认超时为 10 秒,但如您的错误消息中所述,大约需要 30 秒。

在主节点上计算集群状态,然后通过 Elasticsearch 的MasterService.java 类发布 Diff(节点存在)或整个集群状态(如果有新节点加入集群)。

您没有大量的分片信息,这些信息在集群状态中维护,您的主节点无法在默认10s 内计算状态。

下面是来自 Elasticsearch 类 org.elasticsearch.cluster.service.ClusterApplierService 的代码,它尝试更新集群状态并抛出此异常。

try {
    UpdateTask updateTask = new UpdateTask(config.priority(), source, new SafeClusterApplyListener(listener, logger), executor);
    if (config.timeout() != null) {
        threadPoolExecutor.execute(updateTask, config.timeout(),
            () -> threadPool.generic().execute(
                () -> listener.onFailure(source, new ProcessClusterEventTimeoutException(config.timeout(), source))));
    } else {
        threadPoolExecutor.execute(updateTask);
    }
}

您可以检查异常类org.elasticsearch.cluster.metadata.ProcessClusterEventTimeoutException代码如下

public ProcessClusterEventTimeoutException(TimeValue timeValue, String source) {
        super("failed to process cluster event (" + source + ") within " + timeValue);
    }

你可以看看上面的代码,这将有助于你更好地理解问题。

一些解决问题的建议:

  1. 增加主节点的堆大小和CPU,以便可以像您的情况一样快速计算集群状态,即使第一步计算也需要30秒。这意味着您的主节点没有足够的基础架构来快速计算它。
  2. 删除不必要的索引,这将减少分片数量和集群状态。
  3. 以下是发布集群状态的设置,这是第二步,如果您发现发布需要很长时间,那么如果数据节点在此期间不可用,您可以执行此操作。
cluster.publish.info_timeout = 10s default(maybe this can work)
cluster.publish.timeout = 30s by default

【讨论】:

  • 确实,我们有办法减少分片的数量,我们会这样做的。谢谢!
  • @MondKin,请不要忘记将其标记为答案,如果它解决了您的问题,请点赞:-)
  • @MondKin 我不建议每个节点超过 1500 个分片(最好保持在 1000 以下)
  • 感谢大家的帮助!我们将 master 中的堆从 8GB 增加到 16GB,这似乎大大改善了这种情况。我们仍然看到一些消息告诉我们计算集群状态花费了太长时间,但它们比以前少了。我们尚未将数据节点中的堆从 16GB 增加到 32GB。我们还减少了分片数量,但由于我们系统的动态性,这是一个缓慢的过程。我们只减少了 30k 中的 100 个分片,因此目前很难判断这是否有助于系统。
  • @MondKin 很高兴听到反馈,是的,这种问题不会仅仅通过一次改进就消失,有时需要一系列的恢复才能达到理想的状态,但我很高兴你正在前进朝着正确的方向前进。
猜你喜欢
  • 1970-01-01
  • 2020-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-16
  • 1970-01-01
  • 2014-09-18
相关资源
最近更新 更多