bulk写es超时问题

13次阅读

共计 1945 个字符,预计需要花费 5 分钟才能阅读完成。

背景

笔者维护的线上 EFK 集群,在每天早上 8 点创建新索引的时候,日志中总会出现如下的日志:

failed to process cluster event (cluster_update_settings) within 30s
[2019-04-13T08:00:38,213][DEBUG][o.e.a.b.TransportShardBulkAction] [logstash-felice-query-2019.04.13][2] failed to execute bulk item (index) BulkShardRequest [[logstash-felice-query-2019.04.13][2]] containing [7] requests
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:124) ~[elasticsearch-6.3.0.jar:6.3.0]
        at java.util.ArrayList.forEach(ArrayList.java:1257) ~[?:1.8.0_152]
        at org.elasticsearch.cluster.service.MasterService$Batcher.lambda$onTimeout$1(MasterService.java:123) ~[elasticsearch-6.3.0.jar:6.3.0]
        at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingRunnable.run(ThreadContext.java:625) ~[elasticsearch-6.3.0.jar:6.3.0]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_152]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_152]
        at java.lang.Thread.run(Thread.java:748) [?:1.8.0_152]

问题原因

简言之:es 的 master 处理不过来了,es 的 segment 合并是一个非常耗时的操作。
批量处理的超时时间默认设置为 30s。
可以通过以下命令查看 pending 的 task:

curl 'localhost:9200/_cat/pending_tasks?v'

网上说法不一,出现这个问题很可能的原因可以总结如下:

  1. 分片数过多;单节点的分片数不要超过 1000 个(经验值);
  2. 通过写入数据自动创建索引最容易出现这种情况;
  3. 大批量写入数据 refresh 时间间隔太短;
  4. 索引的字段数量太多(几十上百个)

解决方案

方案一:每天预创建索引

虽然普通的 EFK 日志服务可以通过 logstash 的默认模板去创建索引,但是当索引个数比较大,并且索引的字段数量太多时,就非常容易出现超时。那么我们一般的做法是提前创建好索引,并且设定好每个索引的 mapping。
笔者采用了一种偷懒的操作,写了一个定时任务,每天去读取当天的索引的 mapping,然后直接用这个 mapping 去创建新的索引。当然这种解决方案的前提是你自己已经对索引有了一个基本的管理。

方案二:减少每个节点的分片数

es 默认为每个索引设置的分片数是 5。可以通过以下命令查看索引的 settings:

GET /logstash-sonofelice-2019.04.27

可以在创建索引的时候,优化一下分片的个数。可以参考文章:https://www.cnblogs.com/gugul…
一句话:shard 越少越好。shard 越少,越能减少写入开销。

方案三:集群扩容

如果是偶发性的写入超时,可能是流量高峰或者新创建索引的时候创建 mapping 新字段导致。
但是如果经常性的出现超时,并且 write_queue 里面的数据太多,cpu 使用率居高不下,那可能就是 es 集群出现了瓶颈,这时候就需要进行扩容,没有更好的办法。

参考资料

https://github.com/elastic/el…

正文完
 0