ES 5.4+ 引起的Kibana性能問題

原載于Elastic中文社區(qū): https://elasticsearch.cn/article/269

上周有用戶在社區(qū)發(fā)了一例Kibana讀取超時的問題:question#2319 压彭。周末找時間幫其調(diào)查了下穴墅,發(fā)現(xiàn)某些較新的ES版本和Kibana搭配俺叭,會產(chǎn)生意想不到的緩慢問題纵菌。 考慮到這個問題比較普遍菱阵,因此在這里總結(jié)一下問題的根源和解決辦法颁褂,希望用到問題版本的用戶不要踩到坑席里。

首先問題的現(xiàn)象在上面的問題鏈接里有描述签则,簡而言之就是對于一個硬件配置比較高的集群遥诉,每天寫入一個20億左右數(shù)據(jù)的索引拇泣,通過kibana的discovery面板查看數(shù)據(jù)會一直超時。即使時間范圍放到最近半小時矮锈,超時依舊霉翔,有些蹊蹺。

周末拿到用戶給的測試賬號苞笨,登陸集群看了下狀態(tài)债朵。 從機器的硬件配置,集群和索引的配置看瀑凝,沒找到什么特別不對勁的地方序芦。然而點擊到Discovery面板,的確數(shù)據(jù)顯示不出來粤咪。 集群監(jiān)控數(shù)據(jù)看谚中,并沒有其他用戶在做查詢,cpu利用率和集群負載都比較低寥枝。因此初步可以判定宪塔,就是查詢本身比較緩慢所致。

對于診斷查詢緩慢問題囊拜,我通常的做法某筐,就是將對應面板下的查詢拷貝出來,在Kibana Dev Console里手動執(zhí)行冠跷,然后再加上"profile":true選項南誊,看看查詢是如何解析和執(zhí)行的。對應的查詢形如下面這樣:

{
  "profile": true,
  "query": {
    "bool": {
      "must": [
        {
          "query_string": {
            "analyze_wildcard": true,
            "query": "*"
          }
        },
        {
          "range": {
            "@timestamp": {
              "gte": "now-1h",
              "lte": "now",
              "format": "epoch_millis"
            }
          }
        }
      ]
    }
  }
}

因為用戶query框什么都沒有輸入蜜托,因此默認查詢串被Kibana設(shè)置為*抄囚, 然后根據(jù)選擇的時間范圍加了一個range查詢。 profile的輸出讓我稍微有些吃驚盗冷,其中 query_string的里的*居然被解析成非常復雜的DisjunctionMaxQuery怠苔,主要查詢耗時都在這里了。

{
                    "type": "DisjunctionMaxQuery",
                    "description": "(ConstantScore(_field_names:remote_addr.keyword) | ConstantScore(_field_names:geoip.country_isocode) | ConstantScore(_field_names:geoip.country_name.keyword) | ConstantScore(_field_names:via) | ConstantScore(_field_names:domain.keyword) | ConstantScore(_field_names:request_method.keyword) | ConstantScore(_field_names:protocol) | ConstantScore(_field_names:xff.keyword) | ConstantScore(_field_names:host) | ConstantScore(_field_names:geoip.city_name.keyword) | ConstantScore(_field_names:client_ip) | ConstantScore(_field_names:host.keyword) | ConstantScore(_field_names:geoip.longitude) | ConstantScore(_field_names:geoip.subdivision_name.keyword) | ConstantScore(_field_names:geoip.country_code) | ConstantScore(_field_names:upstream_addr.keyword) | ConstantScore(_field_names:@version.keyword) | ConstantScore(_field_names:request_uri) | ConstantScore(_field_names:tags) | ConstantScore(_field_names:idc_tag) | ConstantScore(_field_names:size) | ConstantScore(_field_names:http_referer) | ConstantScore(_field_names:message.keyword) | ConstantScore(_field_names:domain) | ConstantScore(_field_names:geoip.latitude) | ConstantScore(_field_names:xff) | ConstantScore(_field_names:protocol.keyword) | ConstantScore(_field_names:geoip.country_code.keyword) | ConstantScore(_field_names:status) | ConstantScore(_field_names:upstream_addr) | ConstantScore(_field_names:http_referer.keyword) | ConstantScore(_field_names:tags.keyword) | ConstantScore(_field_names:client_ip.keyword) | ConstantScore(_field_names:request_method) | ConstantScore(_field_names:upstream_status) | ConstantScore(_field_names:request_time) | ConstantScore(_field_names:geoip.location) | ConstantScore(_field_names:@version) | ConstantScore(_field_names:geoip.country_name) | ConstantScore(_field_names:user_agent) | ConstantScore(_field_names:idc_tag.keyword) | ConstantScore(_field_names:remote_addr) | ConstantScore(_field_names:geoip.country_isocode.keyword) | ConstantScore(_field_names:geoip.city_name) | ConstantScore(_field_names:via.keyword) | ConstantScore(_field_names:message) | ConstantScore(_field_names:user_agent.keyword) | ConstantScore(_field_names:request_uri.keyword) | ConstantScore(_field_names:@timestamp) | ConstantScore(_field_names:upstream_response_time) | ConstantScore(_field_names:geoip.subdivision_name))",
                    "time": "5535.127008ms",
                    "time_in_nanos": 5535127008

也就是說仪糖, ES將只含一個*query_string query解析成了針對mapping里能找到的所有字段的field:*查詢柑司,然后合并所有的查詢結(jié)果迫肖。 可想而知,對于比較大攒驰,字段比較多的索引這個查詢是非常耗時的蟆湖。而我對于*的認知,是其應該被rewrite成一個match_all query即可玻粪,這樣幾乎沒有什么開銷隅津。

為什么會這樣? 查詢了一下ES官方關(guān)于Query String Query的文檔劲室,其中的default_field和all_fields起到了一定作用:
elasticsearch/reference/5.5/query-dsl-query-string-query.html

default_field

The default field for query terms if no prefix field is specified. Defaults to the index.query.default_field index settings, which in turn defaults to _all.

all_fields

Perform the query on all fields detected in the mapping that can be queried. Will be used by default when the _all field is disabled and no default_field is specified (either in the index settings or in the request body) and no fields are specified.

根據(jù)解釋伦仍,查詢的時候可以帶一個default_field選項,其默認值為索引級別設(shè)置index.query.default_field很洋,如果這個設(shè)置沒有設(shè)置充蓝,則默認為_all。 但一般用戶索引日志的時候喉磁,都會關(guān)掉_all字段谓苟,用于節(jié)省磁盤空間,提升索引速率协怒。那么這時候default_field是什么呢涝焙? 答案是all_fields,也就是ES會將查詢轉(zhuǎn)換為對所有字段的查詢孕暇。

為了驗證這個是問題所在仑撞,我在索引里加了一個default_field的設(shè)置,隨意挑選了一個字段芭商。 果然問題就解決了派草,discovery面板渲染速度快了差不多有10倍搀缠。

但仔細想想铛楣,這也只是繞過了問題。 問題的根源艺普,為什么*不被rewrite成match_all呢簸州?

這時候想到我們自己生產(chǎn)的集群似乎沒有這個問題,于是用我們自己的集群測試了一下,*果然是正常解析成match_all了歧譬。 于是對比了一下集群ES的版本岸浑,我們正常工作的是5.3.2,用戶的集群是5.5.0瑰步。

接下來矢洲,我想找到這些版本之間,ES對于query string的解析源碼層面做了什么改動缩焦。經(jīng)過一番探查读虏,找到了下面這個變更歷史:



可以看到责静,在pull/23433里,為了修復一個foo:*解析歧義的問題盖桥,對于未指定field名稱灾螃,光提供一個*的Query string查詢,不再被解析成match_all了揩徊,而是擴展成全部字段的DisjunctionMaxQuery查詢腰鬼。 由此Kibana默認的*,會引起非常嚴重的性能問題塑荒。

注意: 這個問題會影響5.4和5.5兩個小版本的ES/Kibana熄赡。

順著這個issue里的鏈接摸下去,找到了對應Kibana相關(guān)問題討論:issues#12097齿税,以及對應的修復: pull/13047本谜,修復版本默認發(fā)出的查詢串是match all

修復的版本則是5.5.25.6.0偎窘, 因此有用到5.4.05.5.1之間版本的ELK用戶一定要安排升級乌助!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市陌知,隨后出現(xiàn)的幾起案子他托,更是在濱河造成了極大的恐慌,老刑警劉巖仆葡,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赏参,死亡現(xiàn)場離奇詭異,居然都是意外死亡沿盅,警方通過查閱死者的電腦和手機把篓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來腰涧,“玉大人韧掩,你說我怎么就攤上這事〗颜。” “怎么了疗锐?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長费彼。 經(jīng)常有香客問我滑臊,道長,這世上最難降的妖魔是什么箍铲? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任雇卷,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘关划。我一直安慰自己膘融,他們只是感情好,可當我...
    茶點故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布祭玉。 她就那樣靜靜地躺著氧映,像睡著了一般。 火紅的嫁衣襯著肌膚如雪脱货。 梳的紋絲不亂的頭發(fā)上岛都,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天,我揣著相機與錄音振峻,去河邊找鬼臼疫。 笑死,一個胖子當著我的面吹牛扣孟,可吹牛的內(nèi)容都是我干的烫堤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼凤价,長吁一口氣:“原來是場噩夢啊……” “哼鸽斟!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起利诺,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤富蓄,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后慢逾,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體立倍,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年侣滩,在試婚紗的時候發(fā)現(xiàn)自己被綠了口注。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡君珠,死狀恐怖寝志,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情葛躏,我是刑警寧澤澈段,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布狐赡,位于F島的核電站肥照,受9級特大地震影響钞螟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜摩窃,卻給世界環(huán)境...
    茶點故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧猾愿,春花似錦鹦聪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至姻僧,卻和暖如春规丽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背撇贺。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工赌莺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人松嘶。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓艘狭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親翠订。 傳聞我的和親對象是個殘疾皇子巢音,可洞房花燭夜當晚...
    茶點故事閱讀 45,500評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 歡迎訪問我的博客查看原文:http://wangnan.tech 注:文本整理自《ELKstack權(quán)威指南》 目錄...
    GhostStories閱讀 10,441評論 0 7
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)尽超,斷路器港谊,智...
    卡卡羅2017閱讀 134,696評論 18 139
  • 一、環(huán)境搭建 軟件版本: Linux:centos7 64bit JDK:1.8.0 elasticsearch:...
    lailai900201閱讀 3,581評論 0 12
  • 博客原文一博客原文二 翻譯作品橙弱,水平有限歧寺,如有錯誤,煩請留言指正棘脐。原文請見 官網(wǎng)英文文檔 起步 Elasticse...
    rabbitGYK閱讀 3,261評論 0 68
  • 早上與先生上班路上聊到教育與學習斜筐, 有些人覺得自己身邊不讀書而很有錢的人很多呢?所以自己當年那么辛苦學習蛀缝,希望現(xiàn)在...
    宸世間閱讀 182評論 1 0