每個Elasticsearch節(jié)點內(nèi)部都維護著多個線程池拐邪,如index慰毅、search、get扎阶、bulk等汹胃,用戶可以修改線程池的類型和大小,線程池默認(rèn)大小跟CPU邏輯一致东臀。
一着饥、查看當(dāng)前線程組狀態(tài)
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
}
}
上面截取了部分線程池的配置,其中惰赋,最需要關(guān)注的是rejected宰掉。當(dāng)某個線程池active==threads時,表示所有線程都在忙赁濒,那么后續(xù)新的請求就會進(jìn)入queue中轨奄,即queue>0,一旦queue大小超出限制流部,如bulk的queue默認(rèn)50戚绕,那么elasticsearch進(jìn)程將拒絕請求(碰到bulk HTTP狀態(tài)碼429),相應(yīng)的拒絕次數(shù)就會累加到rejected中枝冀。
當(dāng)我將數(shù)據(jù)寫入集群時舞丛,收到類似于以下內(nèi)容的錯誤消息:
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]"
簡短描述
當(dāng) Elasticsearch 集群收到大量請求且無法再接收任何請求時耘子,通常會發(fā)生“es_rejected_execution_exception”異常。每個節(jié)點都有一個線程池隊列球切,可以容納 50 到 200 個請求谷誓,具體取決于您使用的 Elasticsearch 版本。隊列已滿時吨凑,將拒絕新請求捍歪。
解決方法
注意:在大多數(shù)ES 版本中,無法增加隊列大小鸵钝。該隊列存在的原因是它將請求限制為可管理的數(shù)量糙臼。有關(guān)更多信息,請參閱 Elasticsearch 文檔中的“線程池”部分恩商。
通過下列某一種方法解決“es_rejected_execution_exception”錯誤:
- 添加更多節(jié)點:每個節(jié)點都有一個批量隊列变逃,因此添加更多節(jié)點可以為您提供更多的排隊容量。要添加節(jié)點怠堪,請參閱配置 Amazon ES 域(控制臺)揽乱。
- 切換到更大的實例類型:對于批量請求,每個節(jié)點上線程池中的線程數(shù)等于可用處理器的數(shù)量粟矿。切換到具有更多虛擬 CPU (vCPU) 的實例凰棉,以獲取更多線程來處理批量請求。有關(guān)更多信息陌粹,請參閱選擇實例類型和測試撒犀。
- 優(yōu)化批量請求大小:不是發(fā)送許多小批量請求申屹,而是發(fā)送一些大批量請求绘证。
- 改善索引性能:當(dāng)文檔編制索引速度更快時,批量隊列不太可能達(dá)到容量哗讥。有關(guān)性能優(yōu)化的更多信息嚷那,請參閱 Elasticsearch 文檔中的索引性能提示。
實際使用的解決方法是:
- 1杆煞、記錄失敗的請求并重發(fā)
- 2魏宽、減少并發(fā)寫的進(jìn)程個數(shù),同時加大每次bulk請求的size
二决乎、核心線程池
- index:此線程池用于索引和刪除操作队询。它的類型默認(rèn)為fixed,size默認(rèn)為可用處理器的數(shù)量构诚,隊列的size默認(rèn)為300蚌斩。
- search:此線程池用于搜索和計數(shù)請求。它的類型默認(rèn)為fixed范嘱,size默認(rèn)為可用處理器的數(shù)量乘以3送膳,隊列的size默認(rèn)為1000员魏。
- suggest:此線程池用于建議器請求。它的類型默認(rèn)為fixed叠聋,size默認(rèn)為可用處理器的數(shù)量撕阎,隊列的size默認(rèn)為1000。
- get:此線程池用于實時的GET請求碌补。它的類型默認(rèn)為fixed虏束,size默認(rèn)為可用處理器的數(shù)量,隊列的size默認(rèn)為1000厦章。
- bulk:此線程池用于批量操作镇匀。它的類型默認(rèn)為fixed,size默認(rèn)為可用處理器的數(shù)量闷袒,隊列的size默認(rèn)為50坑律。
- percolate:此線程池用于預(yù)匹配器操作。它的類型默認(rèn)為fixed囊骤,size默認(rèn)為可用處理器的數(shù)量,隊列的size默認(rèn)為1000冀值。
三也物、線程池類型
- 1、Scaling 類型
可變數(shù)量的線程,Elasticsearch會根據(jù)工作負(fù)載自動調(diào)節(jié)線程大小(值介于:core 到 max 之間)以现。
Scaling 類型線程使用示例如下:
thread_pool:
warmer:
core: 1
max: 8
- 2衡未、fixed 類型
有著固定大小的線程池,大小由size屬性指定枷踏,允許你指定一個隊列(使用queue_size屬性指定)用來保存請求,直到有一個空閑的線程來執(zhí)行請求。如果Elasticsearch無法把請求放到隊列中(隊列滿了)斥赋,該請求將被拒絕。
Fixed 類型線程使用示例如下:
thread_pool:
write:
size: 30
queue_size: 1000
- 3产艾、fixed_autoqueue_size 線程
- 固定數(shù)量的線程疤剑,隊列大小會動態(tài)變化以保持目標(biāo)響應(yīng)時間。
- 該功能 8.0+ 版本會廢棄闷堡,這里也不著重講解隘膘。
fixed_autoqueue_size 類型線程使用示例如下:
強調(diào)了隊列大小可變。
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
四杠览、修改線程池配置
- 1弯菊、elasticsearch.yml
threadpool.index.type: fixed
threadpool.index.size: 100
threadpool.index.queue_size: 500
- 2、Rest API
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.......]
這個錯誤明顯是默認(rèn)大小為50的隊列(queue)處理不過來了管钳,解決方法是增大bulk隊列的長度
elasticsearch.yml
threadpool.bulk.queue_size: 1000
六吨悍、線程池使用舉例
若要查看哪些線程 CPU 利用率高或花費的時間最長,可以使用以下查詢蹋嵌。
GET /_nodes/hot_threads
該 API 有助于排查性能問題育瓜。
更多推薦:深入解讀 Elasticsearch 熱點線程 hot_threads
七、線程池和隊列認(rèn)知
認(rèn)知 1:必要時設(shè)置:processors
值得注意的是栽烂,線程池是根據(jù) Elasticsearch 在基礎(chǔ)硬件上檢測到的線程數(shù)(number of processors)設(shè)置的躏仇。
如果檢測失敗,則應(yīng)在 elasticsearch.yml 中顯式設(shè)置硬件中可用的線程數(shù)腺办。
特別是在一臺宿主機配置多個 Elasticsearch 節(jié)點實例的情況下焰手,若要修改其中一個節(jié)點線程池或隊列大小,則要考慮配置 processors 參數(shù)怀喉。
elasticsearch.yml 中設(shè)置如下所示:
processors: 4
PS:Linux 查看線程數(shù)方法:
grep 'processor' /proc/cpuinfo | sort -u | wc -l
認(rèn)知 2:線程池關(guān)聯(lián)隊列設(shè)置
大多數(shù)線程池還具有與之關(guān)聯(lián)的隊列书妻,以使 Elasticsearch 可以將請求存儲在內(nèi)存中,同時等待資源變得可用來處理請求躬拢。
但是躲履,隊列通常具有有限的大小,如果超過該大小聊闯,Elasticsearch將拒絕該請求工猜。
認(rèn)知 3:很糟糕做法——盲目修改隊列大小
有時你可能會增加隊列的大小以防止請求被拒絕,但要結(jié)合資源實際進(jìn)行修改菱蔬,千萬別盲目修改篷帅。
實際上,如果值設(shè)置的非常大拴泌,甚至可能適得其反魏身。因為通過設(shè)置更大的隊列大小,該節(jié)點將需要使用更多的內(nèi)存來存儲隊列蚪腐,這就意味著將剩下相對較少的內(nèi)存來響應(yīng)和管理實際請求箭昵。
此外,增加隊列大小還會增加將操作響應(yīng)保留在隊列中的時間長度削茁,從而導(dǎo)致客戶端應(yīng)用程序面臨超時問題宙枷。
認(rèn)知 4:加強監(jiān)控
通常,唯一有需要增加隊列大小的情況是:在請求數(shù)量激增導(dǎo)致無法在客戶端管理此過程且資源使用率并未達(dá)到峰值茧跋。
你可以借助 Kibana Stack Monitoring 可視化監(jiān)控指標(biāo)以更好地了解 Elasticsearch 集群的性能慰丛。
Kibana 監(jiān)控面板中的總視圖、節(jié)點視圖瘾杭、索引視圖如下所示:
-
總視圖監(jiān)控
-
節(jié)點視圖監(jiān)控
-
索引視圖監(jiān)控
上圖是:Kibana 7.6 版本中的監(jiān)控截圖诅病,標(biāo)紅的地方是在批量寫入數(shù)據(jù)。
- search Rate:檢索速率
- search Latency:檢索延時
- indexing Rate:寫入速度
- indexing Latency:寫入延時
隊列的增加(Growing)表明 Elasticsearch難以滿足請求,而拒絕(rejection)則表明隊列已經(jīng)增長到 Elasticsearch 拒絕的程度贤笆。
需要檢查導(dǎo)致隊列增加的根本原因蝇棉,并嘗試通過在客戶端減輕相關(guān)寫入或檢索操作來平衡對集群線程池的壓力。
八芥永、線程池線上實戰(zhàn)問題及注意事項
8.1 線程池和隊列修改需要更改配置文件 elasticsearch.yml
- 節(jié)點級別配置篡殷,而不再支持 5.X 之前的版本動態(tài) setting 修改。
- 重啟集群后生效埋涧。
8.2 reject 拒絕請求的原因有多種
如果 Elasticsearch 集群開始拒絕索引/寫入(index)請求板辽,則可能有多種原因。
通常棘催,這表明一個或多個節(jié)點無法跟上索引 / 刪除 / 更新 / 批量請求的數(shù)量劲弦,從而導(dǎo)致在該節(jié)點上建立隊列且隊列逐漸累積。
一旦索引隊列超過隊列的設(shè)置的最大值(如 elasticsearch.yml 定義的值或者默認(rèn)值)醇坝,則該節(jié)點將開始拒絕索引請求邑跪。
排查方法:需要檢查線程池的狀態(tài),以查明索引拒絕是否總是在同一節(jié)點上發(fā)生呼猪,還是分布在所有節(jié)點上画畅。
GET /_cat/thread_pool?v
- 如果 reject 僅發(fā)生在特定的數(shù)據(jù)節(jié)點上,那么您可能會遇到負(fù)載平衡或分片問題郑叠。
- 如果 reject 與高 CPU 利用率相關(guān)聯(lián)夜赵,那么通常這是 JVM 垃圾回收的結(jié)果,而 JVM 垃圾回收又是由配置或查詢相關(guān)問題引起的乡革。
- 如果集群上有大量分片,則可能存在過度分片的問題摊腋。
- 如果觀察到節(jié)點上的隊列拒絕沸版,但監(jiān)控發(fā)現(xiàn) CPU 未達(dá)到飽和,則磁盤寫入速度可能存在問題兴蒸。
8.3 寫入 bulk 值要遞進(jìn)步長調(diào)優(yōu)
不要妄圖快速提高寫入速度视粮,一下調(diào)很大,很大勢必會寫入 reject橙凳。
首先嘗試一次索引 100 個文檔蕾殴,然后索引 200 個,再索引 400 個岛啸,依此類推......
當(dāng)索引寫入速度(indexing rate)開始趨于平穩(wěn)時钓觉,便知道已達(dá)到數(shù)據(jù)批量請求的最佳大小。
九坚踩、小結(jié)
寫入 reject荡灾、“429 too many requests” 等都是非常常見的錯誤,問題多半和線程池和隊列大小有關(guān)系,需要結(jié)合業(yè)務(wù)場景進(jìn)行問題排查批幌。
其它參數(shù)設(shè)置
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