ElasticSearch——线程池设置以及EsRejected

2023-01-11  本文已影响0人  小波同学

每个Elasticsearch节点内部都维护着多个线程池,如index、search、get、bulk等,用户可以修改线程池的类型和大小,线程池默认大小跟CPU逻辑一致。

一、查看当前线程组状态

curl -XGET 'http://localhost:9200/_nodes/stats?pretty'
"thread_pool": {
    "bulk": {
        "threads": 32,
        "queue": 0,
        "active": 0,
        "rejected": 0,
        "largest": 32,
        "completed": 659997
    },
    "index": {
        "threads": 2,
        "queue": 0,
        "active": 0,
        "rejected": 0,
        "largest": 2,
        "completed": 2
    }
}

上面截取了部分线程池的配置,其中,最需要关注的是rejected。当某个线程池active==threads时,表示所有线程都在忙,那么后续新的请求就会进入queue中,即queue>0,一旦queue大小超出限制,如bulk的queue默认50,那么elasticsearch进程将拒绝请求(碰到bulk HTTP状态码429),相应的拒绝次数就会累加到rejected中。

当我将数据写入集群时,收到类似于以下内容的错误消息:

error":"elastic: Error 429 (Too Many Requests): rejected execution of org.elasticsearch.transport.TransportService$7@b25fff4 on 
EsThreadPoolExecutor[bulk, queue capacity = 50, org.elasticsearch.common.util.concurrent.EsThreadPoolExecutor@768d4a66[Running, 
pool size = 4, active threads = 4, queued tasks = 50, completed tasks = 820898]] [type=es_rejected_execution_exception]"

简短描述

Elasticsearch 集群收到大量请求且无法再接收任何请求时,通常会发生“es_rejected_execution_exception”异常。每个节点都有一个线程池队列,可以容纳 50 到 200 个请求,具体取决于您使用的 Elasticsearch 版本。队列已满时,将拒绝新请求。

解决方法

注意:在大多数ES 版本中,无法增加队列大小。该队列存在的原因是它将请求限制为可管理的数量。有关更多信息,请参阅 Elasticsearch 文档中的“线程池”部分

通过下列某一种方法解决“es_rejected_execution_exception”错误:

实际使用的解决方法是:

二、核心线程池

三、线程池类型

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

thread_pool:
    warmer:
        core: 1
        max: 8

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

thread_pool:
    write:
        size: 30
        queue_size: 1000

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

四、修改线程池配置

threadpool.index.type: fixed
threadpool.index.size: 100
threadpool.index.queue_size: 500
curl -XPUT 'localhost:9200/_cluster/settings' -d '{
    "transient": {
        "threadpool.index.type": "fixed",
        "threadpool.index.size": 100,
        "threadpool.index.queue_size": 500
    }
}'

五、bulk异常排查

使用es bulk api时报错如下 EsRejectedExcutionException[rejected execution(queue capacity 50) on.......]

这个错误明显是默认大小为50的队列(queue)处理不过来了,解决方法是增大bulk队列的长度

elasticsearch.yml

threadpool.bulk.queue_size: 1000

六、线程池使用举例

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

GET /_nodes/hot_threads

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

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

七、线程池和队列认知

认知 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 监控面板中的总视图、节点视图、索引视图如下所示:

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

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

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

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

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

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

如果 Elasticsearch 集群开始拒绝索引/写入(index)请求,则可能有多种原因。

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

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

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

GET /_cat/thread_pool?v

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

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

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

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

九、小结

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

其它参数设置

thread_pool.search.queue_size: 500
thread_pool.search.size: 200
thread_pool.search.min_queue_size: 10
thread_pool.search.max_queue_size: 1000
thread_pool.search.auto_queue_frame_size: 2000
thread_pool.search.target_response_time: 6s
 
thread_pool.bulk.queue_size: 1024
 
cluster.routing.allocation.disk.include_relocations: false
 
indices.memory.index_buffer_size: 15%
 
indices.breaker.total.limit: 30%
indices.breaker.request.limit: 6%
indices.breaker.fielddata.limit: 3%
 
indices.query.bool.max_clause_count: 300000
indices.queries.cache.count: 500
indices.queries.cache.size: 5%

参考:
https://blog.csdn.net/aa5305123/article/details/86542105

https://blog.csdn.net/hyx216/article/details/90179300

https://blog.csdn.net/laoyang360/article/details/114267168

https://www.dovov.com/searchesrejectedexecutionexceptionsearch.html

https://www.bbsmax.com/A/rV57p7oWdP/

上一篇 下一篇

猜你喜欢

热点阅读