ElasticSearch 的 MasterService 计算集群状态花费的时间太长并抛出 ProcessClusterEventTimeoutException

Dan*_*iel 3 elasticsearch

我们有一个每秒向 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) [?:?]
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

您知道这些错误消息是关于什么的吗?

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

谢谢。

笔记:

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

Ami*_*wal 6

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

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

您有大量的分片信息,这些信息保存在集群状态中,您的主节点无法在 default 内计算状态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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

解决问题的一些建议:

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