Elasitcsearch CPU 使用率突然飆升,怎么辦?
1、引言
本系列文章介紹如何修復(fù) Elasticsearch 集群的常見錯(cuò)誤和問題。
這是系列文章的第二篇,主要探討:Elasitcsearch CPU 使用率突然飆升,怎么辦?
2、Elasticsearch 高CPU 使用率的內(nèi)涵
線上環(huán)境 Elasticsearch CPU 使用率飆升常見問題如下:

——來自《死磕Elasticsearch 知識(shí)星球》
Elasticsearch 使用線程池來管理并發(fā)操作的 CPU 資源。
關(guān)于線程池和隊(duì)列,推薦閱讀:Elasticsearch 線程池和隊(duì)列問題,請(qǐng)先看這一篇。
Elasticsearch 高 CPU 使用率通常意味著一個(gè)或多個(gè)線程池不足以支撐業(yè)務(wù)需求。
如果線程池資源耗盡,Elasticsearch 將拒絕與線程池相關(guān)的請(qǐng)求。
例如,如果搜索線程池(search thread pool)耗盡,Elasticsearch 將拒絕搜索請(qǐng)求,直到有更多線程可用。

上圖更直觀的解釋了線程池、隊(duì)列、客戶端請(qǐng)求之間的關(guān)系,拿檢索線程為例:
當(dāng)請(qǐng)求比較少時(shí),線程池完全可以處理過來; 當(dāng)前再多一些時(shí),需要線程池隊(duì)列排隊(duì); 如果請(qǐng)求再多,就超出了線程池和隊(duì)列的最大負(fù)載,導(dǎo)致 異常報(bào)錯(cuò)。
3、診斷 Elasticsearch 高 CPU 使用率
3.1 核查 CPU 使用率
使用 ?cat nodes API 獲取每個(gè)節(jié)點(diǎn)的當(dāng)前 CPU 使用率。
GET?_cat/nodes?v=true&s=cpu:desc
返回結(jié)果:

如上所示,CPU 即為 cpu 使用率,name 為節(jié)點(diǎn)的名稱。
也可以借助 Kibana Stack Monitoring 進(jìn)行可視化監(jiān)控,CPU 監(jiān)控如下紅圈所示:

3.2 核查熱點(diǎn)線程
如果某個(gè)節(jié)點(diǎn)的 CPU 使用率很高,請(qǐng)使用節(jié)點(diǎn)熱點(diǎn)線程 API 檢查該節(jié)點(diǎn)上運(yùn)行的資源密集型線程。
GET?_nodes/my-node,my-other-node/hot_threads
此 API 以純文本形式返回任何熱點(diǎn)線程的細(xì)節(jié)。
4、降低 CPU 使用率的實(shí)操方案
以下 Tips 概述了 CPU 使用率高的最常見原因及其解決方案。
4.1 擴(kuò)展集群
繁重的數(shù)據(jù)寫入(indexing)和搜索負(fù)載會(huì)耗盡較小的線程池。
為了更好地處理繁重的工作負(fù)載,向集群添加更多節(jié)點(diǎn)或升級(jí)(擴(kuò)容)現(xiàn)有節(jié)點(diǎn)以增加容量。
4.2 分散批量請(qǐng)求
批量請(qǐng)求雖然比單個(gè)請(qǐng)求效率更高,但大型批量寫入或多搜索請(qǐng)求需要大量 CPU 資源。
如果可能,提交較小的請(qǐng)求并在它們之間留出更多時(shí)間。
這里的較小有多???需要結(jié)合業(yè)務(wù)實(shí)際、結(jié)合線程池和隊(duì)列大小不斷調(diào)出最優(yōu)值。
4.3 取消長(zhǎng)時(shí)間運(yùn)行的搜索
長(zhǎng)時(shí)間運(yùn)行的搜索會(huì)阻塞搜索線程池中的線程。
要檢查這些搜索,請(qǐng)使用任務(wù)管理 API。
GET?_tasks?actions=*search&detailed
上述命令行響應(yīng)的描述包含檢索請(qǐng)求及其查詢細(xì)節(jié),其中:running_time_in_nanos 顯示搜索運(yùn)行了多長(zhǎng)時(shí)間。
{
??"nodes"?:?{
????"oTUltX4IQMOUUVeiohTt8A"?:?{
??????"name"?:?"my-node",
??????"transport_address"?:?"127.0.0.1:9300",
??????"host"?:?"127.0.0.1",
??????"ip"?:?"127.0.0.1:9300",
??????"tasks"?:?{
????????"oTUltX4IQMOUUVeiohTt8A:464"?:?{
??????????"node"?:?"oTUltX4IQMOUUVeiohTt8A",
??????????"id"?:?464,
??????????"type"?:?"transport",
??????????"action"?:?"indices:data/read/search",
??????????"description"?:?"indices[my-index],?search_type[QUERY_THEN_FETCH],?source[{\"query\":...}]",
??????????"start_time_in_millis"?:?4081771730000,
??????????"running_time_in_nanos"?:?13991383,
??????????"cancellable"?:?true
????????}
??????}
????}
??}
}
可以使用 _cancel API 取消任務(wù)以釋放資源:
POST?_tasks/oTUltX4IQMOUUVeiohTt8A:464/_cancel
4.4 避免耗費(fèi)資源的搜索
舉例:前綴匹配的 wildcard 查詢、多重聚合或分桶設(shè)置過大的單重聚合都會(huì)非常耗費(fèi)資源。
避免策略包含但不限于:
避免腳本 script檢索。少使用: fuzzy、regexp、prefix、wildcard檢索避免將 range檢索應(yīng)用到text和keyword類型。避免多表關(guān)聯(lián) Join類型。使用 index.max_result_window索引設(shè)置降低大小限制。使用 search.max_buckets集群設(shè)置降低允許的聚合桶的最大數(shù)量。使用 search.allow_expensive_queries集群設(shè)置禁用耗費(fèi)資源的查詢。
5、小結(jié)
建議提前做好集群監(jiān)控和指標(biāo)預(yù)警工作,“防范于未然”,結(jié)合節(jié)點(diǎn)的 CPU 核數(shù)最大化的提升線程池和隊(duì)列的使用率。
你在實(shí)戰(zhàn)環(huán)節(jié)有沒有遇到高 CPU 利用率問題?你是如何解決的呢?歡迎留言交流細(xì)節(jié)。
和你一起,死磕 Elasticsearch!
參考
1.? https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html#query-dsl-allow-expensive-queries
2. https://www.elastic.co/guide/en/elasticsearch/reference/current/fix-common-cluster-issues.html#avoid-expensive-searches
3. https://www.elastic.co/guide/en/elasticsearch/reference/current/fix-common-cluster-issues.html 4. https://qbox.io/blog/thread-pools-elasticsearch-search-request-errors/
推薦
更短時(shí)間更快習(xí)得更多干貨!
已帶領(lǐng)88位球友通過 Elastic 官方認(rèn)證!

