原文載于Elastic中文社區(qū): https://elasticsearch.cn/article/120
嘗鮮
10月26日蓬痒,Elasticsearch5.0.0 GA終于放出筒占,攜程ES Ops團(tuán)隊(duì)也在第一時(shí)間在DEV和UAT環(huán)境分別進(jìn)行了2.4.0 至5.0.0的升級(jí)和測(cè)試留量。升級(jí)完成后,除了部分Query不向前兼容(主要是Filtered Query)横辆,需要在應(yīng)用端做一些修改以外策吠,未發(fā)現(xiàn)其他問題。通過監(jiān)控系統(tǒng)看對(duì)比升級(jí)前后的主要系統(tǒng)指標(biāo)指孤,在同等索引量的情況下启涯,CPU使用率有明顯下降 ( 30% - 50%左右) ,相信性能方面5.0應(yīng)該是有較大提升的恃轩。
在測(cè)試環(huán)境穩(wěn)定運(yùn)行了2周以后结洼,我們決定選定一個(gè)生產(chǎn)集群進(jìn)行升級(jí),考驗(yàn)新版本在更為復(fù)雜的用戶環(huán)境下的表現(xiàn)叉跛。 出于對(duì)業(yè)務(wù)影響最小化的考慮松忍,用于日志分析的集群被圈定為升級(jí)目標(biāo)。該集群也是攜程十幾個(gè)集群中規(guī)模最大的一個(gè)筷厘,共有120個(gè)數(shù)據(jù)結(jié)點(diǎn)運(yùn)行于70臺(tái)物理機(jī)上鸣峭,總數(shù)據(jù)量接近1PB宏所。
升級(jí)前需要做一些準(zhǔn)備工作,下載官方的Migration Helper插件摊溶,檢查集群設(shè)置和索引的兼容性爬骤。對(duì)于不兼容的配置項(xiàng),MH會(huì)詳盡列出更扁,其中標(biāo)注為紅色部分為為升級(jí)前必須修改項(xiàng)盖腕。1.x版本創(chuàng)建的索引,是無(wú)法直接升級(jí)到5的浓镜,需要先在2.x集群里做一次reindex 溃列。 MH提供了不兼容索引掃描功能,對(duì)于找到的不兼容索引膛薛,可以直接在UI上發(fā)起reindex操作听隐,等待結(jié)束即可。 如果是用于業(yè)務(wù)搜索集群哄啄,數(shù)據(jù)可能比較重要雅任,建議升級(jí)前做一個(gè)Snapshot,萬(wàn)一升級(jí)過程出現(xiàn)意外咨跌,可以回退版本從備份里快速恢復(fù)數(shù)據(jù)沪么。我們的日志集群數(shù)據(jù)量極大,也沒有對(duì)數(shù)據(jù)100%不丟的要求锌半,因此升級(jí)前沒有做Snapshot禽车。 做完所有的準(zhǔn)備工作后,預(yù)先通知所有用戶集群升級(jí)的時(shí)間以及可能產(chǎn)生的影響刊殉,選定了周五深夜用戶低峰期殉摔,開始正式升級(jí)工作。
首先通過Ansible將新版本批量部署到所有結(jié)點(diǎn)并統(tǒng)一配置记焊,緊接著對(duì)原有集群做了Full Stop逸月,校驗(yàn)所有的ES已經(jīng)停下后,開始Full Start遍膜。整個(gè)過程比較順利碗硬,所有結(jié)點(diǎn)正常啟動(dòng),數(shù)據(jù)恢復(fù)完成后瓢颅,集群重新回到正常服務(wù)狀態(tài)恩尾。
周末兩天運(yùn)行,未發(fā)現(xiàn)有任何的異樣惜索,CPU利用率也降了不少特笋,看起來(lái)很靠譜……直到周一
踏坑
周一早上剃浇,隨著用戶訪問量高峰來(lái)臨巾兆,馬上浮現(xiàn)出一個(gè)詭異的現(xiàn)象: 索引速率遇到了瓶頸猎物,數(shù)據(jù)開始在前置的消息隊(duì)列(Kafka)里堆積。 從監(jiān)控?cái)?shù)據(jù)看角塑,盡管所有的數(shù)據(jù)結(jié)點(diǎn)CPU消耗都比上周同期低蔫磨,磁盤IO也很低,但索引速率卻低了很多圃伶。反復(fù)對(duì)比查看升級(jí)前后各類監(jiān)控指標(biāo)后堤如,終于發(fā)現(xiàn)一個(gè)可疑點(diǎn),所有結(jié)點(diǎn)的網(wǎng)絡(luò)流量比升級(jí)前高了好幾倍窒朋! 在集群架構(gòu)上搀罢,我們是單獨(dú)架設(shè)了幾臺(tái)client node做為數(shù)據(jù)寫入和分發(fā)的入口,現(xiàn)在這幾個(gè)node的網(wǎng)絡(luò)流量已經(jīng)飽和侥猩,成為數(shù)據(jù)寫入的瓶頸榔至。一開始,懷疑是否2.4啟用了tcp壓縮欺劳,而5.0取消了唧取,但翻查官方文檔后發(fā)現(xiàn)transport.tcp.compress在2.4和5.0里默認(rèn)都是關(guān)閉的! 這時(shí)候只有兩個(gè)解決辦法了划提,要么啟用tcp壓縮枫弟,要么擴(kuò)容client node。 先考慮了一下tcp壓縮的方案鹏往,快速扒了一下ES源碼淡诗,在transport.TcpTransport這個(gè)類里,sendRequest和sendResponse兩個(gè)方法會(huì)根據(jù)transport.tcp.compress
設(shè)置來(lái)決定發(fā)送的消息是否要經(jīng)過壓縮掸犬,而在messageReceived
方法則會(huì)讀取消息頭部的狀態(tài)信息袜漩,探測(cè)消息是否經(jīng)過壓縮以及壓縮的方法,而后決定是否需要解壓湾碎,以及采用的解壓方式宙攻。 這樣看起來(lái),ES是允許tcp壓縮和不壓縮的結(jié)點(diǎn)之間通訊的介褥,那么只對(duì)client node啟用壓縮應(yīng)該就可以了座掘。測(cè)試環(huán)境測(cè)試過后,驗(yàn)證了想法的可行性柔滔。于是對(duì)生產(chǎn)的client node開啟tcp壓縮溢陪,同時(shí)在數(shù)據(jù)發(fā)送端(hangout的ES output)也啟用tcp壓縮,重啟client node后入口網(wǎng)絡(luò)流量降到和之前2.4差不多的程度睛廊,問題得到規(guī)避形真。 針對(duì)這個(gè)問題在Github上提交了issues#21612, 但未得到官方合理的解釋超全。
解決好這個(gè)問題咆霜,另外一個(gè)問題來(lái)了邓馒,很多執(zhí)行大量歷史數(shù)據(jù)搜索的用戶反映出不了結(jié)果。 從監(jiān)控?cái)?shù)據(jù)看蛾坯,這類查詢的搜索耗時(shí)非常久光酣,直到網(wǎng)關(guān)300秒超時(shí)(查詢api前置的nginx代理)。我們之前對(duì)集群設(shè)置過Global Search timeout為60s脉课,用來(lái)保護(hù)集群資源過多被超高代價(jià)的查詢消耗救军,在2.4版本是有效果的,現(xiàn)在看來(lái)不起作用了倘零。手動(dòng)測(cè)試了一下唱遭,這個(gè)參數(shù)果然失效! 于是向官方報(bào)告了第2個(gè)問題:issues#21595呈驶。 這個(gè)問題很快被官方確認(rèn)為Bug胆萧,修復(fù)也很快加入到了5.0.2。 為了規(guī)避這個(gè)問題俐东,我們只好臨時(shí)修改了一下Kibana以及第三方API訪問要經(jīng)過的nginx proxy跌穗,默認(rèn)為所有的search request加入一個(gè)超時(shí)選項(xiàng)。此后虏辫,問題有一些緩解蚌吸,但仍然發(fā)現(xiàn)用戶查詢大范圍歷史數(shù)據(jù)時(shí),部分用于存儲(chǔ)歷史數(shù)據(jù)的結(jié)點(diǎn)響應(yīng)很慢砌庄。
我們的集群是做了冷熱分離的結(jié)構(gòu)的羹唠,熱節(jié)點(diǎn)主要承擔(dān)寫入和存放過去24小時(shí)數(shù)據(jù),冷結(jié)點(diǎn)沒有寫入娄昆,查詢頻率也低佩微,所以為了最大化利用硬件資源,一臺(tái)物理機(jī)上跑了3個(gè)實(shí)例萌焰,這樣一臺(tái)128GB內(nèi)存的機(jī)器可以存放下近30TB的索引哺眯。查看冷結(jié)點(diǎn)的監(jiān)控?cái)?shù)據(jù),看到用戶查詢期間磁盤的read IO非常高扒俯,直接將磁盤IO Util%撐到100%奶卓,并且可持續(xù)數(shù)小時(shí),同時(shí)search thread pool有大量的active thread處于無(wú)法完成狀態(tài)撼玄,search queue不斷攀升直至飽和夺姑、開始reject。 表象上看search thread似乎一直在嘗試從磁盤大量讀取數(shù)據(jù)掌猛,一次search甚至可以持續(xù)幾十分鐘至一個(gè)小時(shí)盏浙,耗盡了所有的搜索線程,導(dǎo)致拒絕后續(xù)的搜索服務(wù)。 于是Github上報(bào)了第3個(gè)issue: issues/21611 這個(gè)問題找到解決辦法之前废膘,我們只能通過反復(fù)重啟有問題的冷結(jié)點(diǎn)來(lái)緩解辣往。 和官方討論過程中,得知5.0在Lucene文件訪問方式上有一個(gè)比較大的改動(dòng)殖卑,2.4使用mmapfs讀取索引文件的部分,而5.0以后改為用mmapfs讀取索引文件的全部坊萝。懷疑問題和這個(gè)變動(dòng)有關(guān)孵稽,嘗試將所有索引文件的設(shè)置改為NIOFS后,問題迎刃而解十偶。 搜索性能一下回到了2.4時(shí)代菩鲜,再也沒出現(xiàn)搜索線程超長(zhǎng)時(shí)間執(zhí)行的問題。之后找時(shí)間復(fù)現(xiàn)了這個(gè)問題惦积,并抓取了線程棧接校,看到長(zhǎng)時(shí)間執(zhí)行的搜索線程一直在做Global Ordinal的構(gòu)造工作。 至于為何會(huì)這樣狮崩,還不清楚蛛勉。 從官方給出的信息看,底層索引文件的訪問模式是沒有變化的睦柴,僅僅是將文件讀取方式全部改成了mmapfs诽凌,理論上應(yīng)該性能更好,但是看起來(lái)在我們這種一臺(tái)機(jī)器跑多個(gè)ES實(shí)例坦敌,所有分配的heap為系統(tǒng)緩存3倍的極端用例下侣诵,大范圍的數(shù)據(jù)搜索可能造成過高的磁盤讀IO,集群性能指數(shù)級(jí)下降狱窘。
以上問題前后耗了4天才完全規(guī)避掉杜顺,支持團(tuán)隊(duì)連續(xù)熬夜后集群總算回復(fù)到平穩(wěn)狀態(tài)。然而好景不長(zhǎng)蘸炸,運(yùn)行一段時(shí)間以后躬络,數(shù)據(jù)結(jié)點(diǎn)出現(xiàn)疑似內(nèi)存泄漏現(xiàn)象。結(jié)點(diǎn)總數(shù)據(jù)沒怎么增加搭儒、甚至還有減少的情況下洗鸵,heap使用率一只呈攀升趨勢(shì),Old GC無(wú)法回收內(nèi)存仗嗦。這個(gè)問題對(duì)用戶影響較小膘滨,通過監(jiān)控我們可以及時(shí)發(fā)現(xiàn)內(nèi)存即將用盡的結(jié)點(diǎn),做一次重啟很快就恢復(fù)了稀拐。 為排查根源火邓,我們對(duì)一個(gè)有問題的結(jié)點(diǎn)做了dump,通過MAT工具分析,看到meta data相關(guān)的一個(gè)alias對(duì)象被實(shí)例化了有6600萬(wàn)次之多铲咨! 在Github上提交了第四個(gè)issue: issues#22013躲胳,不多久被確認(rèn)為已知問題pull#21284 ,在5.0.1已經(jīng)修復(fù)。
最后還存在一個(gè)master node內(nèi)存泄漏的問題纤勒,這個(gè)問題在2.4.0時(shí)代就存在了坯苹,升級(jí)到5.0.0以后依然沒有修復(fù)。由于我們的master node和data node是分離的摇天,所以這個(gè)問題比較容易通過監(jiān)控發(fā)現(xiàn)粹湃,解決方式也很簡(jiǎn)單和迅速,重啟master node即可泉坐,對(duì)用戶完全無(wú)影響为鳄。之后不久,5.0.2版本正式發(fā)布腕让,release notes里提到了對(duì)這個(gè)問題的修復(fù) pull#21578孤钦。
上周周末我們將集群rolling upgrade到了5.0.2,global search timeout失效和兩個(gè)內(nèi)存泄漏的問題從根源上解決掉了纯丸。 網(wǎng)絡(luò)流量增大的問題依然存在偏形,仍然需要通過啟用client結(jié)點(diǎn)的transport.tcp.compress規(guī)避。 冷結(jié)點(diǎn)搜索性能的問題沒看到有提及觉鼻,估計(jì)沒解決壳猜,安全起見,還是保持索引的文件系統(tǒng)為NIOFS滑凉。升級(jí)完成運(yùn)行一段時(shí)間后统扳,可以肯定,5.0.2已經(jīng)比較穩(wěn)定畅姊。
心得
升到5.0.2后咒钟,對(duì)于其中一組數(shù)據(jù)結(jié)點(diǎn)這兩天特意加了點(diǎn)索引負(fù)載,通過監(jiān)控?cái)?shù)據(jù)將v5.0.2與2.4.0做實(shí)際運(yùn)行環(huán)境的索引吞吐量對(duì)比若未。
在近似的CPU使用率和load情況下朱嘴,5.0.2能夠支撐更大的吞吐量。另外5.0帶來(lái)的Instant aggregation功能粗合,對(duì)于跨多個(gè)索引的時(shí)序類型數(shù)據(jù)的聚合也可以有效Cache了萍嬉,在使用Kibana的時(shí)候提速感覺非常明顯。
升級(jí)過程雖然遇到很多波折隙疚,但由于集群架構(gòu)上做了角色分離(client,master,data)和冷熱分離壤追,因而Bug引起的故障比較容易被限定在一個(gè)較小的范圍而不至于影響所有的功能和所有的用戶。 故障點(diǎn)定位更加容易供屉,規(guī)避措施也更容易實(shí)施行冰。 部分規(guī)避措施實(shí)施過程中甚至對(duì)用戶是完全無(wú)影響的溺蕉,比如: 重啟內(nèi)存泄漏的master node)。詳盡的監(jiān)控為問題的發(fā)現(xiàn)和診斷提供了有力的支持悼做。
Elasticsearch是非常復(fù)雜的系統(tǒng)疯特,官方的測(cè)試無(wú)法覆蓋所有的用例場(chǎng)景和數(shù)據(jù)規(guī)模,一些極端的應(yīng)用場(chǎng)景可能觸發(fā)某個(gè)深藏的Bug或者缺陷而陷入困境肛走。 因此對(duì)于穩(wěn)定性要求極高的應(yīng)用漓雅,最好還是采用經(jīng)過長(zhǎng)時(shí)間考驗(yàn)的版本,比如v2.4.2朽色。