Elasticsearch 线程池和队列问题,请先看这一篇

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 1、线程池相关线上实战问题问题1:从Kafka消费数据导入 elasticsearch 时,批量 bulk 写入抛异常被拒绝。ES 集群四个节点,其中:两个节点node1和node4 thread pool bulk rejected 30多万条数据,es bulk thread pool 线程数8、队列200, Kafka写线程池 thread数2*cores+cores/2、队列数3。目前是想平衡一下写的速度和 es 处理的速度,不过现在还没有可用环境压测,想问有经验数据或方法参考吗?

image.png

链接

问题2:多套系统使用一套集群,错误日志如下


{"message": "failed to execute pipeline for a bulk request" ,

"stacktrace": ["org.elasticsearch.common.util.concurrent.EsRejectedExecutionException: rejected execution of org.elasticsearch.ingest.IngestService$4@5b522103 on EsThreadPoolExecutor[name = node-2/write, queue capacity = 1024, org.elasticsearch.common.util.concurrent.EsThreadPoolExecutor@19bdbd79[Running, pool size = 5, active threads = 5, queued tasks = 1677, ]]",

针对问题 2,初步排查日志,是大量日志写入造成队列满了,造成集群直接拒绝写入了。


问题 2 初步解决方案:修改默认值、扩大队列,根据业务后续持续观察队列大小,不再出现上述情形。


问题 1、2 都会引出:Elasticsearch 线程池和队列知识点。


2、线程池概览

Elasticsearch 使用线程池(Thread pool )来管理请求并优化集群中每个节点上的资源使用。


3、线程池用途

主要线程池包括:搜索(search)、获取(get)和写入(write)等。


通过运行以下命令可以看到线程池全貌:


GET /_cat/GET /_cat/thread_pool/?v&h=id,name,active,rejected,completed,size,type&pretty&s=type

image.png

其中:


name:代表某一种线程池(写入、检索、刷新或其他)。


type:代表线程数类型。


通过运行上面的命令可以看到每个节点都有许多不同的线程池、线程池的大小和类型,还可以看到哪些节点拒绝了操作。


Elasticsearch根据每个节点中检测到的线程数(number of processors,后面会讲到这个参数)自动配置线程池参数。


4、线程池类型

4.1 Fixed 类型

固定数量的线程,具有固定的队列大小。


Fixed 类型线程使用示例如下:


thread_pool:

   write:

       size: 30

       queue_size: 1000

4.2 Scaling 类型

可变数量的线程,Elasticsearch会根据工作负载自动调节线程大小(值介于:core 到 max 之间)。


Scaling 类型线程使用示例如下:


thread_pool:

   warmer:

       core: 1

       max: 8

4.3 fixed_autoqueue_size 线程

固定数量的线程,队列大小会动态变化以保持目标响应时间。


该功能 8.0+ 版本会废弃,这里也不着重讲解。


fixed_autoqueue_size 类型线程使用示例如下:


强调了队列大小可变。


thread_pool:

   search:

       size: 30

       queue_size: 500

       min_queue_size: 10

       max_queue_size: 1000

       auto_queue_frame_size: 2000

       target_response_time: 1s

5、线程池使用举例

若要查看哪些线程 CPU 利用率高或花费的时间最长,可以使用以下查询。


GET /_nodes/hot_threads

该 API 有助于排查性能问题。


更多推荐:深入解读 Elasticsearch 热点线程 hot_threads


6、线程池和队列认知

认知 1:必要时设置:processors

值得注意的是,线程池是根据 Elasticsearch 在基础硬件上检测到的线程数(number of processors)设置的。


如果检测失败,则应在 elasticsearch.yml 中显式设置硬件中可用的线程数。


特别是在一台宿主机配置多个 Elasticsearch 节点实例的情况下,若要修改其中一个节点线程池或队列大小,则要考虑配置 processors 参数。


elasticsearch.yml 中设置如下所示:


processors: 4

PS:Linux 查看线程数方法:


grep 'processor' /proc/cpuinfo | sort -u | wc -l

认知 2:线程池关联队列设置

大多数线程池还具有与之关联的队列,以使 Elasticsearch 可以将请求存储在内存中,同时等待资源变得可用来处理请求。


但是,队列通常具有有限的大小,如果超过该大小,Elasticsearch将拒绝该请求。


认知 3:很糟糕做法——盲目修改队列大小

有时你可能会增加队列的大小以防止请求被拒绝,但要结合资源实际进行修改,千万别盲目修改。


实际上,如果值设置的非常大,甚至可能适得其反。因为通过设置更大的队列大小,该节点将需要使用更多的内存来存储队列,这就意味着将剩下相对较少的内存来响应和管理实际请求。


此外,增加队列大小还会增加将操作响应保留在队列中的时间长度,从而导致客户端应用程序面临超时问题。


以下的莽撞行为,大家是要实战中避免的。

认知 4:加强监控

通常,唯一有需要增加队列大小的情况是:在请求数量激增导致无法在客户端管理此过程且资源使用率并未达到峰值。


你可以借助 Kibana Stack Monitoring 可视化监控指标以更好地了解 Elasticsearch 集群的性能。


Kibana 监控面板中的总视图、节点视图、索引视图如下所示:


总视图监控

image.png

  • 节点视图监控

image.png

image.png

  • 索引视图监控

image.png

上图是:Kibana 7.6 版本中的监控截图,标红的地方是我在批量写入数据。


search Rate:检索速率


search Latency:检索延时


indexing Rate:写入速度


indexing Latency:写入延时


队列的增加(Growing)表明 Elasticsearch难以满足请求,而拒绝(rejection)则表明队列已经增长到 Elasticsearch 拒绝的程度。


需要检查导致队列增加的根本原因,并尝试通过在客户端减轻相关写入或检索操作来平衡对集群线程池的压力。


7、线程池线上实战问题及注意事项

7.1 线程池和队列修改需要更改配置文件 elasticsearch.yml

节点级别配置,而不再支持 5.X 之前的版本动态 setting 修改。


重启集群后生效。


7.2 reject 拒绝请求的原因有多种

类似文章开头问题 2,如果 Elasticsearch 集群开始拒绝索引/写入(index)请求,则可能有多种原因。


通常,这表明一个或多个节点无法跟上索引 / 删除 / 更新 / 批量请求的数量,从而导致在该节点上建立队列且队列逐渐累积。


一旦索引队列超过队列的设置的最大值(如 elasticsearch.yml 定义的值或者默认值),则该节点将开始拒绝索引请求。


排查方法:需要检查线程池的状态,以查明索引拒绝是否总是在同一节点上发生,还是分布在所有节点上。


GET /_cat/thread_pool?v

如果 reject 仅发生在特定的数据节点上,那么您可能会遇到负载平衡或分片问题。


如果 reject 与高 CPU 利用率相关联,那么通常这是 JVM 垃圾回收的结果,而 JVM 垃圾回收又是由配置或查询相关问题引起的。


如果集群上有大量分片,则可能存在过度分片的问题。


如果观察到节点上的队列拒绝,但监控发现 CPU 未达到饱和,则磁盘写入速度可能存在问题。


7.3 写入 bulk 值要递进步长调优

不要妄图快速提高写入速度,一下调很大,很大势必会写入 reject。


首先尝试一次索引 100 个文档,然后索引 200 个,再索引 400 个,依此类推......


当索引写入速度(indexing rate)开始趋于平稳时,便知道已达到数据批量请求的最佳大小。


8、小结

写入 reject、“429  too many requests” 等都是非常常见的错误,问题多半和线程池和队列大小有关系,需要结合业务场景进行问题排查。


本文“抛砖引玉”,给出线程池和队列相关总结知识。您在实战中遇到的类似问题吗?欢迎留言探讨交流。


参考

https://drscg.tistory.com/640


https://opster.com/elasticsearch-glossary/index-queue-size-is-high/


https://opster.com/elasticsearch-glossary/elasticsearch-threadpool/


https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-threadpool.html


https://opster.com/analysis/elasticsearch-requested-thread-pool-size-for-is-too-large-setting-to-maximum-instead/


推荐:


全网首发!《 Elasticsearch 最少必要知识教程 V1.0 》低调发布


从实战中来,到实战中去——Elasticsearch 技能更快提升方法论


Elasticsearch写入原理深入详解


Elasticsearch性能优化实战指南


让Elasticsearch飞起来!——性能优化实践干货

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
3月前
|
安全
C++11 线程安全的队列模板
C++11 线程安全的队列模板
27 0
|
10月前
|
安全 NoSQL Redis
python|简单探讨一下线程间通信之队列
python|简单探讨一下线程间通信之队列
125 0
|
11月前
|
缓存 算法 安全
面试题 | 徒手写一个非阻塞线程安全队列 ConcurrentLinkedQueue?
面试题 | 徒手写一个非阻塞线程安全队列 ConcurrentLinkedQueue?
57 0
|
安全
使用两个队列,改进耗时线程引起的性能问题的思路及代码
使用两个队列,改进耗时线程引起的性能问题的思路及代码
98 0
|
Java 自动驾驶 小程序
线程池内的线程如果全部忙,提交一个新的任务,会发生什么?队列全部塞满了之后,还是忙,再提交会发生什么?
线程池内的线程如果全部忙,提交一个新的任务,会发生什么?队列全部塞满了之后,还是忙,再提交会发生什么?
线程池内的线程如果全部忙,提交一个新的任务,会发生什么?队列全部塞满了之后,还是忙,再提交会发生什么?
|
JavaScript 前端开发
JS中的进程、线程、任务队列、事件循环、宏任务、微任务、执行栈等概念理解
JS中的进程、线程、任务队列、事件循环、宏任务、微任务、执行栈等概念理解
169 0
|
Java Android开发
【Android 异步操作】线程池 ( Worker 简介 | 线程池中的工作流程 runWorker | 从线程池任务队列中获取任务 getTask )
【Android 异步操作】线程池 ( Worker 简介 | 线程池中的工作流程 runWorker | 从线程池任务队列中获取任务 getTask )
197 0
|
安全 调度 C++
【C++ 语言】线程安全队列 ( 条件变量 | 线程调度 )(二)
【C++ 语言】线程安全队列 ( 条件变量 | 线程调度 )(二)
241 0
【C++ 语言】线程安全队列 ( 条件变量 | 线程调度 )(二)
|
安全 API 调度
Swing 的任务线程与 EDT 事件分发队列模型(下)
Swing 的任务线程与 EDT 事件分发队列模型(下)
158 0
Swing 的任务线程与 EDT 事件分发队列模型(下)
|
安全 API 调度
Swing 的任务线程与 EDT 事件分发队列模型(上)
Swing 的任务线程与 EDT 事件分发队列模型(上)
92 0
Swing 的任务线程与 EDT 事件分发队列模型(上)