1. 硬件配置和集群規(guī)劃
1.1 內(nèi)存
ES是很消耗內(nèi)存的缠诅,消耗的不是JVM的內(nèi)存,一般來說ES用的JVM Heap還是比較少的饭宾,主要是使用機(jī)器的物理內(nèi)存,ES底層基于Lucene赚爵,Lucene是基于磁盤文件來讀寫和保存索引數(shù)據(jù)的,包括倒排索引法瑟、正排索引等冀膝,Lucene的特點(diǎn)就是基于OS FileSystem Cache,盡量將頻繁訪問的磁盤數(shù)據(jù)在操作系統(tǒng)的內(nèi)存中進(jìn)行緩存霎挟,以此來提升磁盤文件讀寫的性能窝剖,ES的性能80%取決于在分配完JVM Heap之后剩下的服務(wù)器物理內(nèi)存,這些系統(tǒng)內(nèi)存將用做ES的磁盤索引文件的緩存氓扛,如果OS Cache能夠緩存更多的磁盤文件的數(shù)據(jù),索引文件的數(shù)據(jù)论笔,那么索引讀寫的性能會(huì)高很多采郎,特別是檢索的性能。
如果大量的索引文件無法緩存在OS Cache中狂魔,那么搜索蒜埋、聚合的時(shí)候大量的請求都是讀寫磁盤文件,性能當(dāng)然是上不去的最楷,檢索和聚合操作的時(shí)間數(shù)據(jù)級(jí)可能有ms級(jí)變?yōu)閟級(jí)整份,假如使用ES基于千萬級(jí)別的數(shù)據(jù)量做搜索待错,要耗費(fèi)10s+,那大概率就是因?yàn)榇罅空埱笞x寫磁盤了烈评。
ES的排序和聚合都會(huì)消耗很多內(nèi)存火俄,所以給ES進(jìn)程分配足夠的JVM Heap內(nèi)存是很重要的,除此之外讲冠,還要給足夠的內(nèi)存給OS FileSystem Cache瓜客。一般而言,除非業(yè)務(wù)的數(shù)據(jù)量很小竿开,比如一些信息管理系統(tǒng)谱仪,要做一個(gè)內(nèi)部的檢索引擎,數(shù)據(jù)量最多百萬級(jí)否彩,那對機(jī)器配置的要求還是很低的疯攒,而如果,業(yè)務(wù)數(shù)據(jù)量過億列荔,甚至達(dá)到百億級(jí)別敬尺,那么單臺(tái)ES節(jié)點(diǎn)的物理內(nèi)存應(yīng)該為64GB。64G的內(nèi)存肌毅,是比較理想的狀態(tài)筷转,根據(jù)實(shí)際的數(shù)據(jù)量來說,有時(shí)32GB和16GB的內(nèi)存也是可以的悬而,但生產(chǎn)環(huán)境很少使用小于8G的內(nèi)存呜舒,另外由于我們會(huì)使用多個(gè)ES節(jié)點(diǎn)來搭建集群,所以每個(gè)ES節(jié)點(diǎn)的內(nèi)存也沒有必要大于64GB笨奠。
1.2 CPU
大多數(shù)的ES集群對于CPU的要求都會(huì)比較低一些袭蝗,因此一臺(tái)機(jī)器有多少個(gè)CPU Core其實(shí)對生產(chǎn)環(huán)境的ES集群部署相對來說沒有那么的重要了,至少?zèng)]有內(nèi)存那么重要般婆。當(dāng)然到腥,肯定是要用多核處理器的,一般來說2個(gè)CPU Core-8個(gè)Cpu Core都是可以的蔚袍。
此外乡范,如果要選擇是較少的CPU Core但是CPU性能很高,還是較多的CPU Core但是CPU性能較為一般啤咽,那么肯定是選擇性能較為一般但是更多的CPU Core晋辆,因?yàn)楦嗟腃PU Core可以提供更強(qiáng)的并發(fā)處理能力,遠(yuǎn)比單個(gè)CPU 性能高帶來的效果更加明顯宇整。
1.3 磁盤
對于ES的生產(chǎn)環(huán)境來說瓶佳,磁盤是非常重要的,尤其是對那些大量寫入的ES集群鳞青,比如互聯(lián)網(wǎng)公司將每天的實(shí)時(shí)日志數(shù)據(jù)以高并發(fā)的速度寫入ES集群霸饲。在服務(wù)器上为朋,磁盤是最慢的那個(gè)資源,所以對于大量寫入的ES集群來說厚脉,會(huì)很容易因?yàn)榇疟P的讀寫性能造成整個(gè)集群的性能瓶頸习寸。
如果我們能夠使用SSD固態(tài)硬盤,那么當(dāng)然是最好的器仗,SSD的性能比機(jī)械硬盤可以高很多倍融涣,可以讓ES的讀寫性能都高很多倍。所以精钮,如果公司的經(jīng)濟(jì)條件允許威鹿,使用固態(tài)硬盤當(dāng)然是最好的。
使用SSD硬盤轨香,那么需要檢查I/O scheduler忽你,需要正確的配置IO scheduler,將數(shù)據(jù)寫入磁盤時(shí)臂容,IO scheduler會(huì)決定什么時(shí)候數(shù)據(jù)才會(huì)真正的寫入磁盤科雳,即把OS Cache中的數(shù)據(jù)刷寫到磁盤中火架,大多數(shù)機(jī)器上漩仙,默認(rèn)的IO scheduler是CFQ酪我,也就是completely fair queuing茅糜,這個(gè)scheduler會(huì)給每個(gè)進(jìn)程都分配一些時(shí)間分片(Time slice),然后會(huì)優(yōu)化每個(gè)進(jìn)程的數(shù)據(jù)如何寫入磁盤中蒜胖,優(yōu)化的思路主要是根據(jù)磁盤的物理布局來決定如何將數(shù)據(jù)寫入磁盤督惰,進(jìn)而提升寫入磁盤的性能采呐,這是針對機(jī)械硬盤做出的優(yōu)化蕉堰,因?yàn)闄C(jī)械硬盤是一種旋轉(zhuǎn)存儲(chǔ)介質(zhì)凌净,是通過機(jī)械旋轉(zhuǎn)磁盤+磁頭進(jìn)行磁盤讀寫的機(jī)制,但是這種默認(rèn)的scheduler執(zhí)行機(jī)制屋讶,對于SSD來說是不太高效的冰寻,因?yàn)镾SD不涉及到機(jī)械磁盤旋轉(zhuǎn)和磁頭讀取這種傳統(tǒng)的讀寫機(jī)制,對于SSD來說皿渗,應(yīng)該用deadline/noop scheduler斩芭,deadline scheduler會(huì)基于寫操作被pending(等待)了多長時(shí)間來進(jìn)行寫磁盤優(yōu)化,而noop scheduler就是一個(gè)簡單的FIFO隊(duì)列先進(jìn)先出的機(jī)制乐疆,調(diào)整IO Scheduler可以帶來很大的性能提升划乖,甚至可以達(dá)到數(shù)百倍。
如果沒有辦法使用SSD诀拭,只能使用機(jī)械硬盤迁筛,那么至少得盡量正確讀寫速度最快的磁盤煤蚌,比如高性能的服務(wù)器磁盤耕挨,此外细卧,無論是對于機(jī)械硬盤還是SSD,使用RAID 0也是一種提升磁盤讀寫速度的高效的方式筒占。RAID 0也被稱之為條帶式(Striping)存儲(chǔ)機(jī)制贪庙,在RAID各種級(jí)別中性能是最高的。RAID 0的基本原理翰苫,是把連續(xù)的數(shù)據(jù)分散存儲(chǔ)到多個(gè)磁盤上進(jìn)行讀寫止邮,也就是對數(shù)據(jù)進(jìn)行條帶式存儲(chǔ)。這樣系統(tǒng)的磁盤讀寫請求就可以被分散到多個(gè)磁盤上并行執(zhí)行奏窑。但是沒有必要使用鏡像或者RAID的其他模式导披,因?yàn)槲覀儾恍枰ㄟ^RAID來實(shí)現(xiàn)數(shù)據(jù)高可用存儲(chǔ),es的replica副本機(jī)制本身已經(jīng)實(shí)現(xiàn)了數(shù)據(jù)高可用存儲(chǔ)埃唯。
最后撩匕,我們要避免跟網(wǎng)絡(luò)相關(guān)的存儲(chǔ)模式(NAS, network-attached storage),比如基于網(wǎng)絡(luò)的分布式存儲(chǔ)模式墨叛。雖然很多供應(yīng)商都說他們的NAS解決方案性能非常高止毕,而且比本地存儲(chǔ)的可靠性更高。但是實(shí)際上用起來會(huì)有很多性能和可靠性上的風(fēng)險(xiǎn)漠趁,一般因?yàn)榫W(wǎng)絡(luò)傳輸會(huì)造成較高的延時(shí)扁凛,同時(shí)還有單點(diǎn)故障的風(fēng)險(xiǎn)。
1.4 網(wǎng)絡(luò)
對于ES這種分布式系統(tǒng)來說闯传,快速而且可靠的網(wǎng)絡(luò)是非常的重要的谨朝。因?yàn)楦咚倬W(wǎng)絡(luò)通信可以讓ES的節(jié)點(diǎn)間通信達(dá)到低延時(shí)的效果,高帶寬可以讓shard的移動(dòng)和恢復(fù)丸边,以及分配等操作更加的快速〉兀現(xiàn)代的數(shù)據(jù)中心的網(wǎng)絡(luò)對于大多數(shù)的集群來說,性能都足夠高了妹窖。比如千兆網(wǎng)卡纬朝,這都是可以的。
但是要避免一個(gè)集群橫跨多個(gè)數(shù)據(jù)中心骄呼,比如異地多機(jī)房部署一個(gè)集群共苛,因?yàn)槟菢拥脑捒鐧C(jī)房,跨地域的傳輸會(huì)導(dǎo)致網(wǎng)絡(luò)通信和數(shù)據(jù)傳輸性能較差蜓萄。ES集群是一種P2P模式的分布式系統(tǒng)架構(gòu)隅茎,而不是Master-Slave主從分布式系統(tǒng)。在ES集群中嫉沽,所有的node都是相等的辟犀,任意兩個(gè)node間的互相通信都是很頻繁和正常的。因此如果部署在異地多機(jī)房绸硕,那么可能會(huì)導(dǎo)致node間頻繁跨地域進(jìn)行通信堂竟,通信延時(shí)會(huì)非常高魂毁,甚至造成集群運(yùn)行頻繁不正常。
就跟NAS存儲(chǔ)模式一樣出嘹,很多供應(yīng)商都說跨地域的多數(shù)據(jù)中心是非诚可靠的,而且低延時(shí)的税稼。一般來說烦秩,可能的確是這樣,但是一旦發(fā)生了網(wǎng)絡(luò)故障郎仆,那么集群就崩潰了只祠。通常來說,跨地域多機(jī)房部署一個(gè)ES集群帶來的效益扰肌,遠(yuǎn)遠(yuǎn)低于維護(hù)這樣的集群所帶來的額外成本铆农。
1.5 單臺(tái)超級(jí)服務(wù)器 VS 少量中等配置服務(wù)器 VS 大量低配服務(wù)器
一般來說,對于ES集群而言狡耻,是建議少量的中等性能的服務(wù)器而不是使用多臺(tái)低性能服務(wù)器墩剖,因?yàn)閷τ谶\(yùn)維和管理來說,管理5個(gè)物理機(jī)組成的ES集群夷狰,遠(yuǎn)遠(yuǎn)比管理100個(gè)虛擬機(jī)組成的ES集群要簡單的多岭皂。但要避免使用那種超大資源量的超級(jí)服務(wù)器,這樣可能造成資源無法完全利用沼头,在一個(gè)物理機(jī)上部署多個(gè)ES節(jié)點(diǎn)爷绘,導(dǎo)致集群的運(yùn)維更加復(fù)雜。
1.6 JVM
建議使用最新的JDK版本进倍,除非ES明確說明要用哪個(gè)JDK版本土至。ES和Lucene都是一種滿足特殊需求的軟件,在Lucene的單元測試和集成測試中猾昆,經(jīng)常會(huì)發(fā)現(xiàn)JVM自身的一些Bug陶因。這些Bug涵蓋的范圍很廣,因此盡量用最新的JDK版本垂蜗,bug會(huì)少一些楷扬。就ES 5.x版本而言,建議用JDK8贴见,而不是JDK7烘苹,同時(shí)JDK6已經(jīng)不再被支持了。
如果我們用Java編寫ES應(yīng)用程序片部,而且在使用Transport Client或者Node Client镣衡,要確保運(yùn)行我們的應(yīng)用程序的JDK版本跟ES服務(wù)器運(yùn)行的JDK版本是一樣的。在ES中,會(huì)使用到Java的一些基本功能廊鸥,例如本地序列化機(jī)制然爆、IP地址,異常信息等等黍图,而JDK7可能在不同的minor版本之間修改序列化格式,所以如果Client和Server的JDK7版本不一致奴烙,可能有序列化的問題助被。
同時(shí)官方推薦,絕對不要隨便調(diào)整JVM的設(shè)置切诀。雖然JVM有幾百個(gè)配置選項(xiàng)揩环,而且我們可以手動(dòng)調(diào)優(yōu)JVM,遇到一個(gè)性能場景的時(shí)候幅虑,每個(gè)人都會(huì)第一時(shí)間想到去調(diào)優(yōu)JVM丰滑,但是ES官方還是推薦我們不要隨便調(diào)節(jié)JVM參數(shù)。因?yàn)镋S是一個(gè)非常復(fù)雜的分布式軟件系統(tǒng)倒庵,ES的默認(rèn)JVM配置都是基于真實(shí)業(yè)務(wù)場景中長期的實(shí)踐得到的褒墨。隨便調(diào)節(jié)JVM配置反而有可能導(dǎo)致集群性能變得更加差,以及出現(xiàn)一些未知的問題擎宝。在很多情況下郁妈,將自定義的JVM配置全部刪除,性能是保持的最好的绍申。
查看ES版本與操作系統(tǒng)和JVM版本的兼容性:https://www.elastic.co/cn/support/matrix
1.7 容量規(guī)劃
在規(guī)劃你的ES集群的時(shí)候噩咪,一般要規(guī)劃你需要多少臺(tái)服務(wù)器,每臺(tái)服務(wù)器要有多少資源极阅,能夠支撐你預(yù)計(jì)的多大的數(shù)據(jù)量胃碾。但是這個(gè)東西其實(shí)不是一概而論的,要視具體的讀寫場景筋搏,包括你執(zhí)行多么復(fù)雜的操作仆百,讀寫QPS來決定的。不過一般而言奔脐,對于很多的中小型公司儒旬,都是建議ES集群承載的數(shù)據(jù)量在10億規(guī)模以內(nèi)。用最合理的技術(shù)做最合理的事情帖族。
這里可以給出幾個(gè)在國內(nèi)使用ES的幾個(gè)場景栈源,ES是做搜索的,當(dāng)然可以做某個(gè)系統(tǒng)的搜索引擎竖般。比如網(wǎng)站或者APP的搜索引擎甚垦,或者是某些軟件系統(tǒng)的搜索引擎,此外ES還可以用來做數(shù)據(jù)分析。做網(wǎng)站或者APP的搜索引擎艰亮,一般數(shù)據(jù)量會(huì)相對來說大一些闭翩,但是通常而言,一個(gè)網(wǎng)站或者APP的內(nèi)容都是有限的迄埃,不會(huì)無限膨脹疗韵,通常數(shù)據(jù)量從百萬級(jí)到億級(jí)不等,因此用于搜索的數(shù)據(jù)都放在ES中是合理的侄非。
一些軟件系統(tǒng)或者特殊項(xiàng)目的搜索引擎蕉汪,根據(jù)項(xiàng)目情況不同,數(shù)據(jù)量也是從百萬量級(jí)到幾十億逞怨,甚至幾百億者疤,或者每日增量幾億,都有可能叠赦,那么此時(shí)就要根據(jù)具體的業(yè)務(wù)場景來決定了驹马。如果數(shù)據(jù)量特別大,日增量都幾億規(guī)模除秀,那么其實(shí)建議不要將每天全量的數(shù)據(jù)都寫入ES中糯累,ES也不適合這種無限規(guī)模膨脹的場景。ES是很耗費(fèi)內(nèi)存的册踩,無限膨脹的數(shù)據(jù)量寇蚊,會(huì)導(dǎo)致我們無法提供足夠的資源來支撐這么大的數(shù)據(jù)量」骱茫可以考慮是不是將部分熱數(shù)據(jù)仗岸,比如最近幾天的數(shù)據(jù),放到ES中做高頻高性能搜索借笙,然后將大量的很少訪問的冷數(shù)據(jù)放大數(shù)據(jù)系統(tǒng)做離線批量處理扒怖,比如Hadoop系統(tǒng)里面。
要讓ES達(dá)到ms級(jí)的響應(yīng)速度业稼,你必須要有足夠的OS Cache去緩存幾乎大部分的索引數(shù)據(jù)盗痒,預(yù)計(jì)一下,你的數(shù)據(jù)量有多大低散,需要多少臺(tái)機(jī)器俯邓,每臺(tái)機(jī)器要多少資源來支撐才可以達(dá)到多大的性能,假如你有100G稽鞭,你有5臺(tái)8核64G的服務(wù)器吩抓,總共大概300G內(nèi)存钳垮,這300G內(nèi)存,一般要分給ES的JVM Heap一半痕貌,就是150G室琢,除了數(shù)據(jù)本身,ES的存儲(chǔ)的時(shí)候贷腕,還要加入一些額外的信息济瓢,所以數(shù)據(jù)磁盤落地大概是150G箕宙,你的系統(tǒng)本身還要使用內(nèi)存锅很,其他服務(wù)可能也要用,所以剩余的150G內(nèi)存是無法將150G數(shù)據(jù)都緩存到OS Cache中的缘揪,所以不是每條請求都會(huì)走內(nèi)存溉瓶,所以這樣的性能不是最好岩馍,根據(jù)經(jīng)驗(yàn),除非是你的機(jī)器的內(nèi)存資源,完全可以容納所有的磁盤文件,否則ES的請求響應(yīng)時(shí)間是秒闻妓,這樣是很正常的。
如果數(shù)據(jù)量在10億以內(nèi)的規(guī)模壳咕,那么一般而言,如果提供5臺(tái)以上的機(jī)器佃乘,每臺(tái)機(jī)器的配置到8核64G的配置囱井,一般而言都能hold住驹尼。當(dāng)然趣避,這個(gè)也看具體的使用場景,如果你讀寫特別頻繁新翎,或者查詢特別復(fù)雜程帕,那么可能還需要更多的機(jī)器資源。如果你要承載更大的數(shù)據(jù)量地啰,那么就相應(yīng)的提供更多的機(jī)器和資源愁拭。
要提升你的ES的性能,最重要的亏吝,還是說規(guī)劃合理的數(shù)據(jù)量岭埠,物理內(nèi)存資源大小。
以上估算是一個(gè)極其粗略的估算蔚鸥,真正的生產(chǎn)環(huán)境需要更精細(xì)的規(guī)劃惜论。
2. 重要的操作系統(tǒng)設(shè)置
理想情況下,Elasticsearch應(yīng)該獨(dú)占整個(gè)服務(wù)器上的資源止喷。
2.1 禁用交換內(nèi)存
大部分OS都會(huì)將磁盤中的熱點(diǎn)數(shù)據(jù)緩存到內(nèi)存中馆类,假如內(nèi)存不足,則使用磁盤來臨時(shí)代替內(nèi)存弹谁,這樣可能會(huì)導(dǎo)致JVM推內(nèi)存中的數(shù)據(jù)甚至整個(gè)JVM執(zhí)行頁被交換到磁盤中乾巧,這對性能非常不利句喜,應(yīng)該不惜一切代價(jià)避免,它可能導(dǎo)致GC持續(xù)數(shù)分鐘而不是毫秒級(jí)別沟于,并且可能導(dǎo)致節(jié)點(diǎn)響應(yīng)緩慢甚至斷開與集群的連接咳胃。
有三種方法可以禁用Swap,首選項(xiàng)就是完全禁用社裆,如果不能完全禁用拙绊,那么是最小化Swap的使用率還是開啟ES的內(nèi)存鎖定,就要取決于你得機(jī)器的資源使用情況了泳秀。
-
禁用swap
- 暫時(shí)禁用
sudo swapoff -a
- 永久禁用swap:修改
/etc/fstab
文件标沪,注釋掉所有的swap
相關(guān)的行
UUID=24f24210-ba32-46b0-83dd-ae024beb6ced / xfs defaults 0 0 UUID=3742cade-c78c-430d-83a0-2984e2b56b15 /boot xfs defaults 0 0 # UUID=e205fcaf-91dd-4e5c-b2ed-55a816a94743 swap swap defaults 0 0
-
減少swap使用率
修改
/etc/sysctl.conf
文件:vm.swappiness = 1
此配置設(shè)置盡量不使用swap,除非在系統(tǒng)緊急情況下
-
ES開啟內(nèi)存鎖定嗜傅,
elasticsearch.yml
bootstrap.memory_lock: true
此配置生效后金句,在啟動(dòng)ES集群的時(shí)候,會(huì)占用在
jvm.options
文件配置的JVM堆內(nèi)存大小的內(nèi)存吕嘀,無論是否使用违寞,都是長期占用,這樣可以避免Elasticsearch使用的JVM堆內(nèi)存被交換到磁盤上偶房,ES集群啟動(dòng)后趁曼,使用以下請求查看此配置是否生效:GET _nodes?filter_path=**.mlockall
如果返回false,則代表鎖定內(nèi)存失敗棕洋,日志中的相關(guān)信息為
Unable to lock JVM Memory
挡闰,最常見的原因是由于權(quán)限不足而無法鎖定內(nèi)存,解決辦法如下(使用其中一個(gè)即可):如果是使用zip或者tar.gz壓縮包安裝的Elasticsearch掰盘,則使用以下任意一個(gè)方法:
- 使用root用戶執(zhí)行
ulimit -l unlimited
- 修改
/etc/security/limits.conf
文件摄悯,將memlock
設(shè)置為unlimited
如果使用RPM包安裝的Elasticsearch,則使用以下任意一個(gè)方法:
-
編輯
/etc/systemd/system/elasticsearch.service.d/override.conf
文件愧捕,沒有的話直接創(chuàng)建奢驯,添加內(nèi)容如下:[Service] LimitMEMLOCK=infinity
或者直接使用
sudo systemctl edit elasticsearch
編輯此文件,同樣也是加入上面的內(nèi)容
然后執(zhí)行
sudo systemctl daemon-reload
命令重新加載配置內(nèi)存無法鎖定的另一個(gè)原因是次绘,掛載臨時(shí)目錄時(shí)使用noexec選項(xiàng)瘪阁,可以通過指定一個(gè)新的臨時(shí)目錄來解決:
export ES_JAVA_OPTS="$ES_JAVA_OPTS -Djna.tmpdir=<path>" ./bin/elasticsearch
- 使用root用戶執(zhí)行
2.2 增加文件描述符的打開個(gè)數(shù)
確保運(yùn)行Elasticsearch的用戶的文件描述符打開數(shù)的上限為65536或更高。
-
以tar.gz壓縮包安裝的Elasticsearch邮偎,需要使用以下方法增加打開文件描述符的上限:
在啟動(dòng)ES集群之前管跺,使用root用戶執(zhí)行
ulimit -n 65536
-
編輯
/etc/security/limits.conf
文件,將nofile
設(shè)置成65536
* soft nofile 65536 * hard nofile 65536
以RPM方式安裝的Elasticsearch則不使用做任何修改钢猛,在安裝過程中已經(jīng)自動(dòng)做過設(shè)置了
2.3 設(shè)置虛擬內(nèi)存
ES使用mmapfs
目錄來存儲(chǔ)index數(shù)據(jù)伙菜,操作系統(tǒng)的默認(rèn)mmap count限制是很低的,可能會(huì)導(dǎo)致OOM命迈,使用以下任意方式解決:
使用root用戶執(zhí)行
sysctl -w vm.max_map_count=262144
-
修改
/etc/sysctl.conf
文件贩绕,加入:vm.max_map_count = 262144
重啟系統(tǒng)火的,使用
sysctl vm.max_map_count
來驗(yàn)證一下數(shù)值是否修改成功
對于使用RPM方式安裝的ES來說,無需這一步修改淑倾,已經(jīng)自動(dòng)修改好了
2.4 設(shè)置線程數(shù)
ES用了很多線程池來應(yīng)對不同類型的操作馏鹤,確保ES用戶能創(chuàng)建的最大線程數(shù)量至少在4096以上,使用root用戶執(zhí)行ulimit -u 4096
來臨時(shí)設(shè)置娇哆,或者編輯/etc/security/limits.conf
文件湃累,添加如下內(nèi)容:
* soft nproc 4096
* hard nproc 4096
來永久修改此配置,同樣碍讨,對于使用RPM方式安裝的ES來說治力,無需這一配置
2.5 DNS緩存設(shè)置
默認(rèn)情況下,Elasticsearch JVM會(huì)無限期的緩存正向解析主機(jī)名勃黍,反向解析主機(jī)名則緩存十秒宵统,Elasticsearch啟動(dòng)后覆蓋了默認(rèn)的配置,改為緩存正向解析主機(jī)名60s覆获,反向解析主機(jī)名緩存時(shí)間不變马澈,這些配置適用于大多數(shù)環(huán)境,如果不是這些默認(rèn)值弄息,可以通過在jvm.options
文件中加入es.networkaddress.cache.ttl=<timeout>
和es.networkaddress.cache.negative.ttl=<time>
的配置來修改痊班。
2.6 開發(fā)模式和生產(chǎn)模式
默認(rèn)情況下,Elasticsearch假設(shè)用戶在開發(fā)模式下工作摹量,如果以上任何設(shè)置的配置都不正確涤伐,將在日志文件中寫入警告,但是用戶仍然可以啟動(dòng)和運(yùn)行Elasticsearch節(jié)點(diǎn)
一旦配置了諸如network.host
之類的網(wǎng)絡(luò)設(shè)置荆永,Elasticsearch就會(huì)認(rèn)為用戶在生產(chǎn)環(huán)境運(yùn)行節(jié)點(diǎn)废亭,并將上述警告升級(jí)為異常国章。 這些異常將按導(dǎo)致Elasticsearch節(jié)點(diǎn)無法啟動(dòng)具钥,這是一項(xiàng)重要的安全措施。
3. Elasticsearch集群配置
Elasticsearch有3個(gè)配置文件:
-
elasticsearch.yml
:Elasticsearch配置文件 -
jvm.options
:Elasticsearch JVM配置文件 -
log4j2.properties
:Elasticsearch日志配置文件
這些配置文件默認(rèn)在${ELASTICSEARCH_HOME}/config目錄下液兽,可以通過設(shè)置環(huán)境變量ES_PATH_CONF
來修改配置目錄的默認(rèn)位置:
export ES_PATH_CONF=/path/to/my/config
elasticsearch.yml
的書寫該是包括以下兩種:
path:
data: /var/lib/elasticsearch
logs: /var/log/elasticsearch
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
如果一些配置在環(huán)境變量中骂删,例如你設(shè)置了環(huán)境變量ELATICSEARCH_DATA_PATH=/data/es
,那么可以在配置文件中讀取這些環(huán)境變量:
path.data: ${ELATICSEARCH_DATA_PATH}
3.1 Elasticsearch基本配置
3.1.1 ES的默認(rèn)參數(shù)
ES的默認(rèn)參數(shù)是非常好的四啰,適合絕大多數(shù)的情況宁玫,尤其是一些性能相關(guān)的配置。因此剛開始部署一個(gè)生產(chǎn)環(huán)境下的es集群時(shí)柑晒,幾乎所有的配置參數(shù)都可以用默認(rèn)的設(shè)置欧瘪。有很多的生產(chǎn)環(huán)境場景下,都是因?yàn)镋S集群管理人員自己去調(diào)整某些配置匙赞,結(jié)果導(dǎo)致集群出現(xiàn)了嚴(yán)重的故障佛掖,比如MySQL或者Oracle這種關(guān)系型數(shù)據(jù)庫妖碉,也許是需要非常重的調(diào)優(yōu),但是ES是真的不用芥被。如果我們現(xiàn)在面臨著一些ES的性能問題欧宜,通常建議的解決方案是更好的進(jìn)行數(shù)據(jù)結(jié)構(gòu)的布局,或者增加更多的節(jié)點(diǎn)和機(jī)器資源拴魄。在ES的性能調(diào)優(yōu)中冗茸,真的很少有那種某個(gè)參數(shù)一調(diào)節(jié),直接性能提升上百倍的情況匹中,即使有這種參數(shù)夏漱,ES官方也早就將其設(shè)置為默認(rèn)的最佳值了。
但是在生產(chǎn)環(huán)境中顶捷,還是有極少數(shù)跟公司和業(yè)務(wù)相關(guān)的配置是需要我們修改的麻蹋。這些設(shè)置都是具體的公司和業(yè)務(wù)相關(guān)聯(lián)的,是沒法預(yù)先給予最好的默認(rèn)配置的焊切。
3.1.2 集群名稱和節(jié)點(diǎn)名稱
默認(rèn)情況下扮授,ES會(huì)啟動(dòng)一個(gè)名稱為my-application
的集群。建議一定要將自己的集群名稱重新進(jìn)行命名专肪,主要是避免公司網(wǎng)絡(luò)環(huán)境中刹勃,某個(gè)開發(fā)人員的測試節(jié)點(diǎn)無意中加入你的集群。
此外嚎尤,每個(gè)node啟動(dòng)的時(shí)候荔仁,ES也會(huì)分配一個(gè)隨機(jī)的名稱。這個(gè)也不適合在生產(chǎn)環(huán)境中芽死,因?yàn)檫@會(huì)導(dǎo)致我們沒法記住每臺(tái)機(jī)器乏梁。而且每次重啟節(jié)點(diǎn)都會(huì)隨機(jī)分配,就導(dǎo)致node名稱每次重啟都會(huì)變化关贵。因此通常我們在生產(chǎn)環(huán)境中是需要給每個(gè)node都分配一個(gè)名稱的
cluster.name: elasticsearch
node.name: node01
3.1.3 文件路徑
- 數(shù)據(jù)目錄遇骑、日志目錄以及插件目錄
默認(rèn)情況下,ES會(huì)將log揖曾、data等重要文件都放在ES的安裝目錄中落萎。這有一個(gè)問題,就是在進(jìn)行ES升級(jí)的時(shí)候炭剪,可能會(huì)導(dǎo)致這些目錄被覆蓋掉练链。導(dǎo)致我們丟失之前安裝好的plugin,已有的log奴拦,還有已有的數(shù)據(jù)媒鼓,以及配置好的配置文件。
所以一般建議在生產(chǎn)環(huán)境中,必須將這些重要的文件路徑绿鸣,都重新設(shè)置一下瓷产,放在ES安裝目錄之外。path.data
用于設(shè)置數(shù)據(jù)文件的目錄枚驻,path.logs
用于設(shè)置日志文件的目錄濒旦,path.data
可以指定多個(gè)目錄,用逗號(hào)分隔即可再登。如果多個(gè)目錄在不同的磁盤上尔邓,那么這就是一個(gè)最簡單的RAID 0的方式,將數(shù)據(jù)在本地進(jìn)行條帶化存儲(chǔ)了锉矢,可以提升整體的磁盤讀寫性能梯嗽。ES會(huì)自動(dòng)將數(shù)據(jù)在多個(gè)磁盤的多個(gè)目錄中條帶化存儲(chǔ)數(shù)據(jù)
path.logs: /var/log/elasticsearch
path.data: /var/data/es1,/var/data/es2
在RAID 0的存儲(chǔ)級(jí)別下,每個(gè)磁盤上回存儲(chǔ)一部分?jǐn)?shù)據(jù)沽损,但是如果一個(gè)磁盤故障了灯节,那么可能導(dǎo)致這臺(tái)機(jī)器上的部分?jǐn)?shù)據(jù)就丟失了。如果我們的ES是有replica的绵估,那么在其他機(jī)器上還是會(huì)有一份副本的炎疆。如果path.data
指定了多個(gè)目錄,為了盡量減少數(shù)據(jù)丟失的風(fēng)險(xiǎn)国裳,ES會(huì)將某個(gè)shard的數(shù)據(jù)都分配到一個(gè)磁盤上去形入。這就意味著每個(gè)shard都僅僅會(huì)放在一個(gè)磁盤上。ES不會(huì)將一個(gè)shard的數(shù)據(jù)條帶化存儲(chǔ)到多個(gè)磁盤上去缝左,因?yàn)槿绻粋€(gè)磁盤丟失了亿遂,會(huì)導(dǎo)致多個(gè)shard的部分?jǐn)?shù)據(jù)丟失。
但是這又引入了性能的問題渺杉,如果我們給一個(gè)機(jī)器添加更多的磁盤來提升單個(gè)索引的讀寫性能蛇数,但這個(gè)索引在這臺(tái)機(jī)器上的shard僅僅存在于一個(gè)磁盤上。因此path.data
指定多個(gè)目錄是越,僅僅對于你的一臺(tái)機(jī)器上存儲(chǔ)了多個(gè)index的多個(gè)shard時(shí)耳舅,才會(huì)有效果的。因?yàn)椴煌琲ndex的shard可能就被存儲(chǔ)到不同的磁盤上去英妓,對多個(gè)index的不同shard讀寫可以走不同磁盤挽放,提升了性能绍赛。
雖多個(gè)data path是一個(gè)很有用的功能蔓纠,但是ES畢竟不是一個(gè)專門的RAID軟件。如果我們要對RAID存儲(chǔ)策略進(jìn)行更多的配置吗蚌,提高存儲(chǔ)的健壯性以及靈活性腿倚,還是要用專門的RAID軟件來進(jìn)行機(jī)器的磁盤數(shù)據(jù)存儲(chǔ),而不是用多個(gè)data path策略蚯妇。
綜上所述敷燎,多個(gè)data path功能在實(shí)際的生產(chǎn)環(huán)境中暂筝,其實(shí)是較少使用的
3.1.4 配置文件目錄
ES的配置文件默認(rèn)存放在$ES_HOME/config下,可以在ES的啟動(dòng)命令中來重新設(shè)置:
./bin/elasticsearch -Epath.conf=/path/to/my/config/
或者在環(huán)境變量中修改默認(rèn)的配置目錄:
export ES_PATH_CONF=/path/to/my/config
3.2 日志配置
ES使用log4j2來記錄日志硬贯,log4j2可以通過log4j2.properties文件來進(jìn)行配置焕襟,比如下面的這份配置文件:
# ${sys:es.logs.base_path}取path.logs的值
# ${sys:es.logs.cluster_name}取cluster.name的值
# ${sys:es.logs.node_name}取node.name的值
# 設(shè)置RollingFile Appender
appender.rolling.type = RollingFile
appender.rolling.name = rolling
# 日志文件名稱,例如/var/log/elasticsearch/production.log
appender.rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] [%node_name]%marker %.-10000m%n
# 滾動(dòng)日志的名稱饭豹,例如/var/log/elasticsearch/production-yyyy-MM-dd-i.log
appender.rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}-%d{yyyy-MM-dd}-%i.log.gz
appender.rolling.policies.type = Policies
# 日志滾動(dòng)策略依賴于時(shí)間
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
# 每天滾動(dòng)一次日志
appender.rolling.policies.time.interval = 1
# 每個(gè)自然天滾動(dòng)一次鸵赖,而不是沒隔24小時(shí)滾動(dòng)一次
appender.rolling.policies.time.modulate = true
# 日志滾動(dòng)策略也依賴于日志文件大小
appender.rolling.policies.size.type = SizeBasedTriggeringPolicy
# 文件超過256M就滾動(dòng)一次
appender.rolling.policies.size.size = 256MB
# 處理滾動(dòng)日志的策略
appender.rolling.strategy.type = DefaultRolloverStrategy
appender.rolling.strategy.fileIndex = nomax
# 刪除滾動(dòng)日志
appender.rolling.strategy.action.type = Delete
appender.rolling.strategy.action.basepath = ${sys:es.logs.base_path}
# 按照日志名稱來刪除滾動(dòng)日志
appender.rolling.strategy.action.condition.type = IfFileName
# 要?jiǎng)h除的日志
appender.rolling.strategy.action.condition.glob = ${sys:es.logs.cluster_name}-*
# 僅當(dāng)累積了太多壓縮日志時(shí)才刪除
appender.rolling.strategy.action.condition.nested_condition.type = IfAccumulatedFileSize
# 積壓的壓縮日志大于2G時(shí)刪除
appender.rolling.strategy.action.condition.nested_condition.exceeds = 2GB
# 根據(jù)最后修改時(shí)間來刪除日志
appender.rolling.strategy.action.condition.nested_condition.type = IfLastModified
# 超過7天還沒有被修改的日志就刪除
appender.rolling.strategy.action.condition.nested_condition.age = 7D
3.3 Zen Discovery集群發(fā)現(xiàn)機(jī)制和Master相關(guān)配置
通常我們在每臺(tái)機(jī)器部署并啟動(dòng)一個(gè)ES進(jìn)程,怎么讓多臺(tái)機(jī)器上的多個(gè)ES進(jìn)程拄衰,互相發(fā)現(xiàn)對方它褪,然后完美的組成一個(gè)ES集群呢?
默認(rèn)情況下翘悉,ES進(jìn)程會(huì)綁定在自己的回環(huán)地址上茫打,也就是127.0.0.1,然后掃描本機(jī)上的9300~9305端口號(hào)妖混,嘗試跟這些端口上啟動(dòng)的其他ES進(jìn)程進(jìn)行通信老赤,然后組成一個(gè)集群聘惦。這對于在本機(jī)上搭建ES集群的開發(fā)環(huán)境是很方便的危尿。但是對于生產(chǎn)環(huán)境下的集群是不行的,需要將每臺(tái)ES進(jìn)程綁定在一個(gè)非回環(huán)的IP地址上嘲恍,才能跟其他節(jié)點(diǎn)進(jìn)行通信息堂,同時(shí)需要使用集群發(fā)現(xiàn)機(jī)制(discovery)來跟其他節(jié)點(diǎn)上的ES node進(jìn)行通信嚷狞,同時(shí)discovery機(jī)制也負(fù)責(zé)ES集群的Master選舉
ES node中有Master Node和Data Node兩種角色。
ES 是一種Peer to Peer荣堰,也就是p2p點(diǎn)對點(diǎn)的分布式系統(tǒng)架構(gòu)床未,不是Hadoop生態(tài)普遍采用的那種Master-Slave主從架構(gòu)的分布式系統(tǒng)。集群中的每個(gè)node是直接跟其他節(jié)點(diǎn)進(jìn)行通信的振坚,幾乎所有的API操作薇搁,比如index,delete渡八,search等都不是Client跟Master通信啃洋,而是Client跟任何一個(gè)node進(jìn)行通信,那個(gè)node再將請求轉(zhuǎn)發(fā)給對應(yīng)的node來進(jìn)行執(zhí)行屎鳍。
兩個(gè)角色宏娄,Master Node,Data Node逮壁。正常情況下孵坚,就只有一個(gè)Master Node。master node的責(zé)任就是負(fù)責(zé)維護(hù)整個(gè)集群的狀態(tài)信息,也就是一些集群元數(shù)據(jù)信息卖宠,同時(shí)在新node加入集群或者從集群中下線時(shí)巍杈,或者是創(chuàng)建或刪除了一個(gè)索引后,重新分配shard扛伍。包括每次集群狀態(tài)如果有改變的化筷畦,那么master都會(huì)負(fù)責(zé)將集群狀態(tài)同步給所有的node。
Master Node負(fù)責(zé)接收所有的集群狀態(tài)變化相關(guān)的信息刺洒,然后將改變后的最新集群狀態(tài)推動(dòng)給集群中所有的Data Node汁咏,集群中所有的node都有一份完整的集群狀態(tài)。只不過Master Node負(fù)責(zé)維護(hù)而已作媚。其他的node攘滩,除了master之外的Data Node,就是負(fù)責(zé)數(shù)據(jù)的讀寫纸泡。
如果要讓多個(gè)Node組成一個(gè)es集群漂问,首先第一個(gè)要設(shè)置的參數(shù),就是cluster.name
女揭,多個(gè)node的cluster.name
一樣蚤假,才滿足組成一個(gè)集群的基本條件。cluster.name
的默認(rèn)值是my-application
吧兔,在生產(chǎn)環(huán)境中磷仰,一定要修改這個(gè)值,否則可能會(huì)導(dǎo)致未知的node無端加入集群境蔼,造成集群運(yùn)行異常灶平。
而ES中默認(rèn)的discovery機(jī)制,就是zen discovery機(jī)制箍土,zen discovery機(jī)制提供了unicast discovery集群發(fā)現(xiàn)機(jī)制逢享,集群發(fā)現(xiàn)時(shí)的節(jié)點(diǎn)間通信是依賴的Transport Module,也就是ES底層的網(wǎng)絡(luò)通信模塊和協(xié)議吴藻。
ES默認(rèn)配置是使用unicast集群發(fā)現(xiàn)機(jī)制瞒爬,從而讓經(jīng)過特殊配置的節(jié)點(diǎn)可以組成一個(gè)集群,而不是隨便哪個(gè)節(jié)點(diǎn)都可以組成一個(gè)集群沟堡。但是默認(rèn)配置下侧但,unicast是本機(jī),也就是localhost航罗,因此只能在一臺(tái)機(jī)器上啟動(dòng)多個(gè)node來組成一個(gè)集群禀横。雖然ES還是會(huì)提供multicast plugin作為一個(gè)發(fā)現(xiàn)機(jī)制,但是已經(jīng)不建議在生產(chǎn)環(huán)境中使用了伤哺。雖然我們可能想要multicast的簡單性燕侠,就是所有的node可以再接收到一條multicast ping之后就立即自動(dòng)加入集群者祖。但是multicast機(jī)制有很多的問題立莉,而且很脆弱绢彤,比如網(wǎng)絡(luò)有輕微的調(diào)整,就可能導(dǎo)致節(jié)點(diǎn)無法發(fā)現(xiàn)對方蜓耻。因此現(xiàn)在建議在生產(chǎn)環(huán)境中用unicast機(jī)制茫舶,提供一個(gè)ES種子節(jié)點(diǎn)作為中轉(zhuǎn)路由節(jié)點(diǎn)就可以了。
另外還需要在集群中規(guī)劃出專門的Master Eligible Node和Data node刹淌,一個(gè)節(jié)點(diǎn)只要它是Master Eligible Node饶氏,才有可能被選舉為真正的Master Node,選舉出真正的Master Node之后有勾,其他的Master Eligible Node疹启,將在Master Node故障之后,通過選舉蔼卡,從中再產(chǎn)生一個(gè)新的Master Node喊崖,同時(shí),所有的非Master Node雇逞,都是Data Node荤懂,也就是說,Master Eligible Node只是有機(jī)會(huì)成為Master Node塘砸,只要你不是Master Node节仿,你就是Data Node,而不是Master Eligible Node的Data Node是沒有升級(jí)成為Master Node的資格的掉蔬。
如果是一個(gè)小集群廊宪,10個(gè)以內(nèi)的節(jié)點(diǎn),那就所有節(jié)點(diǎn)都可以作為Master Eligible Node以及Data node即可女轿,超過10個(gè)node的集群再單獨(dú)拆分Master Eligible Node和Data Node挤忙。
# 設(shè)置為Master Eligible Node
node.master: true
# 設(shè)置為Data Node
node.data: true
默認(rèn)情況下,ES會(huì)將自己綁定到127.0.0.1上谈喳,對于運(yùn)行一個(gè)單節(jié)點(diǎn)的開發(fā)模式下的ES是ok的册烈。但是為了讓節(jié)點(diǎn)間可以互相通信以組成一個(gè)集群,需要讓節(jié)點(diǎn)綁定到一個(gè)IP地址上
network.host: 192.168.0.1
只要不是本地回環(huán)地址婿禽,ES就會(huì)認(rèn)為我們從開發(fā)模式遷移到生產(chǎn)模式赏僧,同時(shí)會(huì)啟用一系列的bootstrap check
ping:ping是一個(gè)node用discovery機(jī)制來發(fā)現(xiàn)其他node的一個(gè)過程
unicast:unicast discovery集群發(fā)現(xiàn)機(jī)制是要求配置一個(gè)主機(jī)列表,這些主機(jī)作為Gossip通信協(xié)議的路由器扭倾,如果通過hostname來指定淀零,那么在ping的時(shí)候會(huì)被解析為IP地址
discovery.zen.ping.unicast.hosts: ["host1", "host2"]
簡單來說,如果要讓多個(gè)節(jié)點(diǎn)發(fā)現(xiàn)對方并且組成一個(gè)集群膛壹,那么就得有一個(gè)中間的公共節(jié)點(diǎn)驾中,當(dāng)不同的節(jié)點(diǎn)發(fā)送請求到這些公共節(jié)點(diǎn)唉堪,通過這些公共節(jié)點(diǎn)交換各自的信息,進(jìn)而讓所有的node感知到其他的node存在肩民,并且進(jìn)行通信唠亚,最后組成一個(gè)集群。這就是基于gossip流言式通信協(xié)議的unicast集群發(fā)現(xiàn)機(jī)制持痰。
當(dāng)一個(gè)node與discovery.zen.ping.unicast.hosts
中的一個(gè)成員通信之后灶搜,就會(huì)接收到一份完整的集群狀態(tài),接著這個(gè)node再跟master通信工窍,并且加入集群中割卖。這就意味著,discovery.zen.ping.unicast.hosts
是不需要列出集群中的所有節(jié)點(diǎn)的患雏,只要提供少數(shù)幾個(gè)node鹏溯,比如3個(gè),讓新的node可以連接上即可淹仑,如果我們給集群中分配了幾個(gè)節(jié)點(diǎn)作為專門的master節(jié)點(diǎn)丙挽,那么這里配置那些master節(jié)點(diǎn)即可,這個(gè)配置中也可以指定端口:
discovery.zen.ping.unicast.hosts: ["host1", "host2:9201"]
為集群選舉出一個(gè)master是很重要的攻人,ES集群會(huì)自動(dòng)完成這個(gè)操作取试,node.master
設(shè)置為false的節(jié)點(diǎn)是無法稱為Master的,discovery.zen.minimum_master_nodes
參數(shù)用于設(shè)置對于一個(gè)ES集群來說怀吻,必須擁有的最少的正常在線的Master Eligible Node的個(gè)數(shù)瞬浓,否則會(huì)發(fā)生"集群腦裂"現(xiàn)象,假如在集群中設(shè)置了3個(gè)Master Eligible Node蓬坡,那么這個(gè)值應(yīng)該為(master_eligible_nodes / 2) + 1
猿棉,即2
discovery.zen.minimum_master_nodes: 2
集群腦裂
discovery.zen.minimum_master_nodes
參數(shù)對于集群的可靠性來說,是非常重要的屑咳。這個(gè)設(shè)置可以預(yù)防腦裂問題萨赁,也就是預(yù)防一個(gè)集群中存在兩個(gè)master。
這個(gè)參數(shù)的作用兆龙,就是告訴ES直到有足夠的master候選節(jié)點(diǎn)時(shí)杖爽,才可以選舉出一個(gè)master,否則就不要選舉出一個(gè)master紫皇。這個(gè)參數(shù)必須被設(shè)置為集群中master候選節(jié)點(diǎn)的quorum數(shù)量慰安,也就是大多數(shù)。quorum的算法聪铺,就是:master候選節(jié)點(diǎn)數(shù)量 / 2 + 1化焕,比如我們有10個(gè)節(jié)點(diǎn),都能維護(hù)數(shù)據(jù)铃剔,也可以是master候選節(jié)點(diǎn)撒桨,那么quorum就是10 / 2 + 1 = 6查刻,如果我們有三個(gè)master候選節(jié)點(diǎn),還有100個(gè)數(shù)據(jù)節(jié)點(diǎn)凤类,那么quorum就是3 / 2 + 1 = 2穗泵,Elasticsearch要求最少有3個(gè)節(jié)點(diǎn),如果我們有2個(gè)節(jié)點(diǎn)踱蠢,都可以是master候選節(jié)點(diǎn)火欧,那么quorum是2 / 2 + 1 = 2棋电。此時(shí)就有問題了茎截,因?yàn)槿绻粋€(gè)Master掛掉了,那么剩下一個(gè)master候選節(jié)點(diǎn)赶盔,是無法滿足quorum數(shù)量的企锌,也就無法選舉出新的master,集群就徹底掛掉了于未。此時(shí)就只能將這個(gè)參數(shù)設(shè)置為1撕攒,如果發(fā)生了網(wǎng)絡(luò)分區(qū),那么兩個(gè)分區(qū)中都會(huì)有一個(gè)Master烘浦,還是無法避免集群腦裂
那么這個(gè)是參數(shù)是如何避免腦裂問題的產(chǎn)生的呢抖坪?比如我們有3個(gè)節(jié)點(diǎn),quorum是2闷叉,現(xiàn)在網(wǎng)絡(luò)故障擦俐,1個(gè)節(jié)點(diǎn)在一個(gè)網(wǎng)絡(luò)區(qū)域,另外2個(gè)節(jié)點(diǎn)在另外一個(gè)網(wǎng)絡(luò)區(qū)域握侧,不同的網(wǎng)絡(luò)區(qū)域內(nèi)無法通信蚯瞧。這個(gè)時(shí)候有兩種情況:
如果master是單獨(dú)的那個(gè)節(jié)點(diǎn),另外2個(gè)節(jié)點(diǎn)是master候選節(jié)點(diǎn)品擎,那么此時(shí)那個(gè)單獨(dú)的master節(jié)點(diǎn)因?yàn)闆]有指定數(shù)量的候選master node在自己當(dāng)前所在的集群內(nèi)埋合,因此就會(huì)取消當(dāng)前master的角色,嘗試重新選舉萄传,但是無法選舉成功甚颂。然后另外一個(gè)網(wǎng)絡(luò)區(qū)域內(nèi)的node因?yàn)闊o法連接到master,就會(huì)發(fā)起重新選舉秀菱,因?yàn)橛袃蓚€(gè)master候選節(jié)點(diǎn)振诬,滿足了quorum,因此可以成功選舉出一個(gè)master答朋。此時(shí)集群中就會(huì)還是只有一個(gè)master贷揽。
如果master和另外一個(gè)node在一個(gè)網(wǎng)絡(luò)區(qū)域內(nèi),然后一個(gè)node單獨(dú)在一個(gè)網(wǎng)絡(luò)區(qū)域內(nèi)梦碗。那么此時(shí)那個(gè)單獨(dú)的node因?yàn)檫B接不上master禽绪,會(huì)嘗試發(fā)起選舉蓖救,但是因?yàn)閙aster候選節(jié)點(diǎn)數(shù)量不到quorum,因此無法選舉出master印屁。而另外一個(gè)網(wǎng)絡(luò)區(qū)域內(nèi)循捺,原先的那個(gè)master還會(huì)繼續(xù)工作。這也可以保證集群內(nèi)只有一個(gè)master節(jié)點(diǎn)雄人。
在ES集群是可以動(dòng)態(tài)增加和下線節(jié)點(diǎn)的从橘,所以可能隨時(shí)會(huì)改變quorum。所以這個(gè)參數(shù)也是可以通過API隨時(shí)修改的础钠,特別是在節(jié)點(diǎn)上線和下線的時(shí)候恰力,都需要作出對應(yīng)的修改。而且一旦修改過后旗吁,這個(gè)配置就會(huì)持久化保存下來踩萎。
PUT /_cluster/settings
{
"persistent" : {
"discovery.zen.minimum_master_nodes": 2
}
}
此外還有一些其他的關(guān)于集群發(fā)現(xiàn)機(jī)制相關(guān)的配置,以下將列出上述討論的參數(shù)以及一些其他的參數(shù)做總結(jié):
#設(shè)置集群為single-node模式,這樣的話,ES將不會(huì)再從外部去發(fā)現(xiàn)其他節(jié)點(diǎn),默認(rèn)不配資,代表可以發(fā)現(xiàn)其他節(jié)點(diǎn)
discovery.type: single-node
discovery.zen.ping.unicast.hosts: ["host1", "host2"]
#主機(jī)名被DNS解析為IP地址的超時(shí)時(shí)間
discovery.zen.ping.unicast.resolve_timeout: 5s
#在決定開始選舉或加入現(xiàn)有集群之前節(jié)點(diǎn)將等待多長時(shí)間
discovery.zen.ping_timeout: 3s
#節(jié)點(diǎn)決定加入現(xiàn)有集群后,向Master發(fā)送加入請求,超時(shí)時(shí)間默認(rèn)discovery.zen.ping_timeout時(shí)間的20倍
discovery.zen.join_timeout: 20
#Master發(fā)送修改集群狀態(tài)的消息給其他節(jié)點(diǎn),如果在此時(shí)間內(nèi)還沒有至少discovery.zen.minimum_master_nodes個(gè)備用Master節(jié)點(diǎn)回復(fù),則此次修改集群狀態(tài)的動(dòng)作不會(huì)發(fā)生
discovery.zen.commit_timeout: 30s
#滿足上面的條件后,Master發(fā)送修改集群狀態(tài)的消息給全部Node,然后全部Node開始修改自身的集群狀態(tài)信息,Master只有會(huì)等待所有的Node響應(yīng),最多等待此處的時(shí)間,然后才會(huì)開始下一次狀態(tài)修改的流程
discovery.zen.publish_timeout: 30s
#設(shè)置集群中備用master的quorum,如果集群中備用的Master的個(gè)數(shù)少于此配置,將引發(fā)集群腦裂的現(xiàn)象
discovery.zen.minimum_master_nodes: 2
#選舉Master的時(shí)候,是否忽略node.master=false的節(jié)點(diǎn)發(fā)送的ping消息,默認(rèn)false
discovery.zen.master_election.ignore_non_master_pings: false
#當(dāng)集群中沒有存活的Master后,禁用外部請求允許的操作,write:外部請求只能讀,不能寫,all:外部請求不能讀寫ES集群
discovery.zen.no_master_block: write
#Master與Data Node互相發(fā)送ping消息的時(shí)間間隔
ping_interval: 1s
#Master與Data Node互相發(fā)送ping消息超時(shí)時(shí)間
ping_timeout: 30s
#Master與Data Node互相發(fā)送ping消息失敗后的重試次數(shù)
ping_retries: 3
3.4 Gateway相關(guān)配置
在集群重啟的時(shí)候很钓,有一些配置會(huì)影響shard恢復(fù)的過程香府。首先,我們需要理解默認(rèn)配置下码倦,shard恢復(fù)過程會(huì)發(fā)生什么事情企孩。如果我們有10個(gè)node,每個(gè)node都有一個(gè)shard袁稽,可能是primary shard或者replica shard勿璃,你有一個(gè)index,有5個(gè)primary shard运提,每個(gè)primary shard有一個(gè)replica shard蝗柔。如果我們將整個(gè)集群關(guān)閉了進(jìn)行一些維護(hù)性的操作,比如給機(jī)器安裝新的磁盤之類的事情民泵。當(dāng)我們重啟集群的時(shí)候癣丧,肯定節(jié)點(diǎn)是一個(gè)接一個(gè)的啟動(dòng)的,可能會(huì)出現(xiàn)5個(gè)節(jié)點(diǎn)先啟動(dòng)了栈妆,然后剩下5個(gè)節(jié)點(diǎn)還沒啟動(dòng)胁编。
也許是因?yàn)槭O碌?個(gè)節(jié)點(diǎn)沒來得及啟動(dòng),或者是因?yàn)橐恍┰虻R了鳞尔,總之不管是什么原因嬉橙,就是現(xiàn)在只有5個(gè)節(jié)點(diǎn)是在線的。這5個(gè)節(jié)點(diǎn)會(huì)通過gossip協(xié)議互相通信寥假,選舉出一個(gè)master市框,然后組成一個(gè)集群。他們會(huì)發(fā)現(xiàn)數(shù)據(jù)沒有被均勻的分布糕韧,因?yàn)橛?個(gè)節(jié)點(diǎn)沒有啟動(dòng)枫振,那么那5個(gè)節(jié)點(diǎn)上的shard就是不可用的喻圃,集群中就少了一半的shard。此時(shí)在線的5個(gè)node就會(huì)將部分replica shard提升為primary shard粪滤,同時(shí)為每個(gè)primary shard復(fù)制足夠的replica shard斧拍。
最后惯殊,剩下的5個(gè)節(jié)點(diǎn)加入了集群糙臼。但是這些節(jié)點(diǎn)發(fā)現(xiàn)本來是他們持有的shard已經(jīng)被重新復(fù)制并且放在之前的5個(gè)node上了伴榔,此時(shí)他們就會(huì)刪除自己本地的數(shù)據(jù)擦盾。然后集群又會(huì)開始進(jìn)行shard的rebalance操作,將最早啟動(dòng)的5個(gè)node上的shard均勻分布到后來啟動(dòng)的5個(gè)node上去希痴。
在這個(gè)過程中另伍,這些shard重新復(fù)制悼瓮,移動(dòng)伟件,刪除硼啤,再次移動(dòng)的過程议经,會(huì)大量的耗費(fèi)網(wǎng)絡(luò)和磁盤資源斧账。對于數(shù)據(jù)量龐大的集群來說,可能導(dǎo)致每次集群重啟時(shí)煞肾,都有TB級(jí)別的數(shù)據(jù)無端移動(dòng)咧织,可能導(dǎo)致集群啟動(dòng)會(huì)耗費(fèi)很長時(shí)間。但是如果所有的節(jié)點(diǎn)都可以等待整個(gè)集群中的所有節(jié)點(diǎn)都完全上線之后籍救,所有的數(shù)據(jù)都有了以后习绢,再?zèng)Q定是否要復(fù)制和移動(dòng)shard,情況就會(huì)好很多蝙昙。
所以現(xiàn)在問題我們已經(jīng)知道了闪萄,那么我們就可以配置一些參數(shù)來解決這個(gè)問題。首先我們需要設(shè)置一個(gè)參數(shù)奇颠,gateway.recover_after_nodes
败去,這個(gè)參數(shù)可以讓ES等待,直到有足夠的node都上線之后烈拒,再開始shard recovery的過程圆裕。所以這個(gè)參數(shù)是跟具體的集群相關(guān)的,要根據(jù)我們的集群中節(jié)點(diǎn)的數(shù)量來決定荆几。此外吓妆,還應(yīng)該設(shè)置一個(gè)集群中至少要有多少個(gè)node,等待這些node的時(shí)間:gateway.expected_nodes
吨铸,gateway.recover_after_time
行拢。
gateway.recover_after_nodes: 3
gateway.expected_nodes: 10
gateway.recover_after_time: 5m
經(jīng)過上面的配置之后,es集群的行為會(huì)變成下面這樣诞吱,等待至少3個(gè)節(jié)點(diǎn)在線且最多等待5分鐘舟奠,或者10個(gè)節(jié)點(diǎn)都在線狈涮,再開始shard recovery的過程。這樣就可以避免少數(shù)node啟動(dòng)時(shí)鸭栖,就立即開始shard recovery歌馍,消耗大量的網(wǎng)絡(luò)和磁盤資源,甚至可以將shard recovery過程從數(shù)小時(shí)縮短為數(shù)分鐘晕鹊。
以下為Gateway相關(guān)配置的總結(jié):
#當(dāng)集群中存在這么多節(jié)點(diǎn)之后,可以立即開始Recovery
gateway.expected_nodes: 0
#當(dāng)集群中存在這么多Master節(jié)點(diǎn)之后,可以立即開始Recovery
gateway.expected_master_nodes: 0
#當(dāng)集群中存在這么多Data節(jié)點(diǎn)之后,可以立即開始Recovery
gateway.expected_data_nodes: 0
#當(dāng)上述條件達(dá)不到的時(shí)候,最多等待多長時(shí)間,開始Recovery
gateway.recover_after_time: 5m
#在等待前3個(gè)條件達(dá)到期間,只要發(fā)現(xiàn)有這么多節(jié)點(diǎn)在線,就開始Recovery
gateway.recover_after_nodes: 3
#在等待前3個(gè)條件達(dá)到期間,只要發(fā)現(xiàn)有這么Master節(jié)點(diǎn)在線,就開始Recovery
gateway.recover_after_master_nodes: 0
#在等待前3個(gè)條件達(dá)到期間,只要發(fā)現(xiàn)有這么多Data節(jié)點(diǎn)在線,就開始Recovery
gateway.recover_after_data_nodes: 0
3.5 JVM配置
通過以下兩種方式來設(shè)置JVM堆內(nèi)存
-
修改
jvm.options
文件-Xms1g -Xmx1g
-
設(shè)置環(huán)境變量
ES_JAVA_OPTS="-Xms2g -Xmx2g" ES_JAVA_OPTS="-Xms4000m -Xmx4000m"
JVM堆內(nèi)存該設(shè)置多大松却?
最小堆內(nèi)存和最大堆內(nèi)存一定要設(shè)置成一樣的
-
將機(jī)器上少于一半的內(nèi)存分配給ES的堆內(nèi)存
雖然Heap對于ES來說是非常重要的,其中存放很多內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)來提供更快的操作性能溅话。但影響ES的性能更大的因素在于系統(tǒng)級(jí)別的緩存晓锻,其中保存著索引文件數(shù)據(jù),所以一定保證有足夠的內(nèi)存用作系統(tǒng)緩存飞几,在一個(gè)只有ES進(jìn)程的服務(wù)器上砚哆,建議把50%的內(nèi)存給堆,把50%的內(nèi)存留給系統(tǒng)緩存屑墨,如果不能滿足這種條件躁锁,寧愿少給JVM Heap也不要少給系統(tǒng)緩存
-
JVM堆內(nèi)存不要大于32GB,如果Heap小于32G卵史,JVM會(huì)用一種技術(shù)來壓縮對象的指針(object pointer)战转,在Java中,所有的對象都會(huì)被分配到Heap中以躯,然后被一個(gè)pointer引用槐秧。object pointer會(huì)指向heap中的對象,引用的是二進(jìn)制格式的地址
對于32位的系統(tǒng)來說忧设,JVM最大的heap size就是4G(2^32/1024/1024/1024)刁标,對于64位的系統(tǒng)來說,heap size可以更大址晕,但是64位的object pointer會(huì)耗費(fèi)更多的空間膀懈,因?yàn)閛bject pointer更大了,比浪費(fèi)更多內(nèi)存空間更惡劣的是斩箫,過大的object pointer會(huì)在cpu吏砂,朱內(nèi)存和LLC、L1等多級(jí)緩存間移動(dòng)數(shù)據(jù)的時(shí)候乘客,消耗更多的帶寬
所以JVM用了一種技術(shù)狐血,叫做compressed oops來解決object pointer耗費(fèi)過大空間的問題。這個(gè)技術(shù)的核心思想是易核,不要讓object pointer引用內(nèi)存中的二進(jìn)制地址匈织,而是讓object pointer引用object offset。這就意味著32位的pointer可以引用400萬個(gè)對象,而不是400萬字節(jié)缀匕。這也意味著纳决,使用32位的pointer,最大的heap大小可以到32G乡小。此時(shí)只要heap size在32G以內(nèi)阔加,jvm就會(huì)自動(dòng)啟用32位的object pointer,因?yàn)?2位的對象指針满钟,足夠引用32G的內(nèi)存了胜榔,就可以用32位的pointer替代64位的pointer。但是32位的pointer比64位的pointer可以耗費(fèi)更少的內(nèi)存耗費(fèi)湃番。
如果給jvm heap分配的內(nèi)存小于32G夭织,此時(shí)jvm會(huì)自動(dòng)使用32位的object pointer,同時(shí)是讓pointer指向?qū)ο蟮膐ffset吠撮,32位的object pointer就足以引用32G的內(nèi)存尊惰,同時(shí)32位的pointer占用的內(nèi)存空間很少,對cpu和memory之間移動(dòng)數(shù)據(jù)的帶寬開銷也很少泥兰。這個(gè)過程就叫做compressed oops弄屡。
但是一旦越過了32G這個(gè)界限,就是給jvm heap分配了超過32G的內(nèi)存逾条,就沒有辦法用32位的pointer+引用object offset的模式了琢岩,因?yàn)?2位的pointer最多引用32G的內(nèi)存。不用32位pointer师脂,就只能用64位pointer,才能引用超過32G的內(nèi)存空間江锨。此時(shí)pointer就會(huì)退回到傳統(tǒng)的object pointer引用對象的二進(jìn)制地址的模式吃警,此時(shí)object pinter的大小會(huì)急劇增長,更多的cpu到內(nèi)存的帶寬會(huì)被占據(jù)啄育,更多的內(nèi)存被耗費(fèi)酌心。實(shí)際上,不用compressed oops時(shí)挑豌,你如果給jvm heap分配了一個(gè)40~50G的內(nèi)存的可用空間安券,object pointer可能都要占據(jù)十幾G的內(nèi)存空間,可用的空間量氓英,可能跟使用了compressed oops時(shí)的32GB內(nèi)存的可用空間幾乎是一樣的侯勉。因此,即使我們有很多內(nèi)存铝阐,但是還是要分配給heap在32GB以內(nèi)址貌,否則的話浪費(fèi)更多的內(nèi)存,降低cpu性能,而且會(huì)讓jvm回收更大的heap练对。
設(shè)置JVM堆內(nèi)存的一個(gè)核心思想是遍蟋,一定要保證compressed oops這種存儲(chǔ)指針的方式是打開的,可以給jvm option加入
-XX:+PrintFlagsFinal
螟凭,然后在啟動(dòng)后查看日志虚青,觀察是否啟用compressed oop,如果開啟了挟憔,可以看到:[env] [Illyana Rasputin] heap size [989.8mb], compressed ordinary object pointers [true]
,根據(jù)實(shí)際經(jīng)驗(yàn)烟号,設(shè)置31GB是保險(xiǎn)的脯燃,而正好設(shè)置為32GB是不敢保證一定打開compressed oop
的补君。超級(jí)計(jì)算機(jī)的內(nèi)存如何分配楣铁?
如果我們的機(jī)器是一臺(tái)超級(jí)服務(wù)器,內(nèi)存資源甚至達(dá)到了1TB椿访,或者512G钦勘,128G陋葡,首先ES官方是建議避免用這種超級(jí)服務(wù)器來部署ES集群的,但是如果公司就是任性彻采,那么:
- 業(yè)務(wù)是否在做大量的全文檢索腐缤?是的話,分配4-31G的內(nèi)存給JVM Heap颊亮,然后全部的內(nèi)存都留給系統(tǒng)緩存
- 業(yè)務(wù)是否在做大量的排序或者聚合操作柴梆?聚合操作是不是針對數(shù)字、日期或者未分詞的未分詞的字符串终惑?如果是的話,那么還是給ES 4-32G的內(nèi)存门扇,其他的留給系統(tǒng)緩存雹有,可以將聚合好用的正排索引,doc values放在os cache中
- 業(yè)務(wù)是否針對分詞的字符串做大量的排序或聚合操作臼寄?如果是的話霸奕,那么就需要使用fielddata,這就得給jvm heap分配更大的內(nèi)存空間吉拳。此時(shí)不建議在服務(wù)器上運(yùn)行一個(gè)ES節(jié)點(diǎn)质帅,而是在服務(wù)器上運(yùn)行多個(gè)節(jié),假如服務(wù)器有128G的內(nèi)存,可以運(yùn)行兩個(gè)ES節(jié)點(diǎn)煤惩,然后每個(gè)節(jié)點(diǎn)分配31G的堆內(nèi)存嫉嘀,剩下的留給OS Cache,如果在一臺(tái)機(jī)器上運(yùn)行多個(gè)ES node魄揉,建議設(shè)置:
cluster.routing.allocation.same_shard.host: true
剪侮,ES的分片要分布在不同的服務(wù)器上,這個(gè)配置的作用是洛退,假如你在A服務(wù)器上啟動(dòng)了3個(gè)ES進(jìn)程瓣俯,在B服務(wù)上啟動(dòng)了3個(gè)ES進(jìn)程,那么這個(gè)配置設(shè)置為true兵怯,就會(huì)保證A服務(wù)器上的3個(gè)進(jìn)程的副本在都在B服務(wù)器上彩匕,設(shè)置為false的話,就不會(huì)進(jìn)行這樣的檢查媒区,默認(rèn)為false驼仪,這個(gè)配置只有在一臺(tái)機(jī)器上啟動(dòng)了多個(gè)ES進(jìn)程時(shí)才有效。但是假如只有一臺(tái)服務(wù)器驻仅,那就所有的ES進(jìn)程都不會(huì)有replica副本了谅畅。
-
JVM配置只要修改堆內(nèi)存的大小即可,其他的參數(shù)例如GC相關(guān)參數(shù)盡量不要調(diào)噪服,原因如下:
JVM使用垃圾回收器來釋放掉不用的內(nèi)存毡泻,千萬不要去調(diào)節(jié)默認(rèn)的垃圾回收行為。ES默認(rèn)用的垃圾回收器是CMS粘优。CMS回收器是并發(fā)式的回收器仇味,能夠跟應(yīng)用程序工作線程并發(fā)工作,最大程度減少垃圾回收時(shí)的服務(wù)停頓時(shí)間雹顺。但是CMS還是會(huì)有兩個(gè)停頓階段丹墨,同時(shí)在回收特別大的heap時(shí)也會(huì)有一些問題。盡管有一些缺點(diǎn)嬉愧,但是CMS對于要求低延時(shí)請求響應(yīng)的軟件來說贩挣,還是最佳的垃圾回收器,因此官方的推薦就是使用CMS垃圾回收器没酣。
有一種最新的垃圾回收器叫做G1王财。G1回收器可以比CMS提供更少的回收停頓時(shí)間,而且能夠這對大heap有更好的回收表現(xiàn)裕便。它會(huì)將heap劃分為多個(gè)region绒净,然后自動(dòng)預(yù)測哪個(gè)region會(huì)有最多可以回收的空間。通過回收那些region偿衰,就可以最小化停頓時(shí)長挂疆,而且可以針對大heap進(jìn)行回收改览。
但是,G1還是比較年輕的一種垃圾回收器缤言,而且經(jīng)常會(huì)發(fā)現(xiàn)一些新的bug宝当,這些bug可能會(huì)導(dǎo)致jvm掛掉。lucene的測試套件就檢查出來了G1的一些bug墨闲。因此ES官方不推薦現(xiàn)在使用G1垃圾回收器今妄,也許在不久的未來,等G1更加穩(wěn)定的時(shí)候鸳碧,可以使用G1盾鳞。
-
線程池相關(guān)參數(shù)也不要調(diào)整
在ES中,默認(rèn)的threadpool設(shè)置是非常合理的瞻离,對于所有的threadpool來說腾仅,除了搜索的線程池,都是線程數(shù)量設(shè)置的跟cpu core一樣多的套利。如果我們有8個(gè)cpu core推励,那么就可以并行運(yùn)行8個(gè)線程。那么對于大部分的線程池來說肉迫,分配8個(gè)線程就是最合理的數(shù)量验辞。
也許我們會(huì)覺得有些線程可能會(huì)因?yàn)榇疟PIO等操作block住,所以我們需要更多的線程喊衫。但是在ES中這并不是一個(gè)問題跌造,大多數(shù)的磁盤IO操作都是由Lucene的線程管理的,而不是由ES管理的族购,因此ES的線程不需要關(guān)心這個(gè)問題壳贪。此外,threadpool還會(huì)通過在彼此之間傳遞任務(wù)來協(xié)作執(zhí)行寝杖,我們不需要擔(dān)心某一個(gè)網(wǎng)絡(luò)線程會(huì)因?yàn)榈却淮未疟P寫操作违施,而導(dǎo)致自己被block住,無法處理網(wǎng)絡(luò)請求瑟幕。網(wǎng)絡(luò)線程可以將那個(gè)磁盤寫操作交給其他線程池去執(zhí)行磕蒲,然后自己接著回來處理網(wǎng)絡(luò)請求。
其實(shí)我們的進(jìn)程的計(jì)算能力是有限的只盹,分配更多的線程只會(huì)強(qiáng)迫CPU在多個(gè)線程上下文之間頻繁來回切換亿卤。一個(gè)cpu core在同一時(shí)間只能運(yùn)行一條線程,所以如果cpu要切換到另外一個(gè)線程去執(zhí)行鹿霸,需要將當(dāng)前的state保存起來,然后加載其他的線程進(jìn)來執(zhí)行秆乳。如果線程上下文切換發(fā)生在一個(gè)cpu core內(nèi)懦鼠,那么還好一些钻哩,但是如果在多個(gè)cpu core之間發(fā)生線程上下文切換,那么還需要走一個(gè)cpu core內(nèi)部的通信肛冶。這種線程上下文切換會(huì)消耗掉很多的cpu資源街氢,對于現(xiàn)在的cpu來說,每次線程上下文切換睦袖,都會(huì)導(dǎo)致30微秒的時(shí)間開銷珊肃,所以寧愿將這些時(shí)間花費(fèi)在任務(wù)的處理上。
也就是說馅笙,線程多了之后伦乔,CPU進(jìn)行多個(gè)線程上下文切換帶來的額外消耗要大于多個(gè)線程提供并發(fā)處理帶來的好處。
4. Bootstrap Checks
- bootstrap check:ES啟動(dòng)時(shí)會(huì)進(jìn)行一些列的檢查董习,確保系統(tǒng)設(shè)置和ES的配置是沒有問題的烈和,包括以下的檢查:
-
development mode vs production mode
默認(rèn)情況下,ES綁定到localhost hostname皿淋,來進(jìn)行http和內(nèi)部通信招刹。這對于簡單測試日常的開發(fā),都是非常方便的窝趣,但是對于生產(chǎn)環(huán)境是不行的症脂。如果要組成一個(gè)ES集群,ES實(shí)例必須能夠通過內(nèi)部通信協(xié)議互相連通宝惰,所必須綁定通信到一個(gè)外部的接口上锦秒。因此如果一個(gè)ES實(shí)例沒有綁定通信到外部接口,那么就認(rèn)為ES是處于開發(fā)模式下散址。反之乖阵,如果綁定通信到外部接口(
network.host
設(shè)置為非本地地址),那么就是處于生產(chǎn)模式下预麸。可以通過
http.host
和transport.host
瞪浸,單獨(dú)配置http的傳輸。這就可以配置一個(gè)ES實(shí)例通過http可達(dá)吏祸,但是卻不觸發(fā)生產(chǎn)模式有時(shí)用戶需要將通信綁定到外部对蒲,解耦來測試client的調(diào)用。對于這種場景贡翘,ES提供了single-node恢復(fù)模式(將
discovery.type
設(shè)置為single-node
)蹈矮,配置過后,一個(gè)節(jié)點(diǎn)會(huì)選舉自己作為master鸣驱,而且不會(huì)跟其他任何節(jié)點(diǎn)組成集群泛鸟。如果在生產(chǎn)模式下運(yùn)行一個(gè)single node實(shí)例,就可以規(guī)避掉啟動(dòng)時(shí)檢查(不綁定到外部接口踊东,或者將通信綁定到外部接口北滥,但是設(shè)置
discovery type
為single-node
)刚操。在這種場景下,可以設(shè)置es.enforce.bootstrap.checks
為true
(通過jvm參數(shù)來設(shè)置再芋,-Des.enforce.bootstrap.checks=true
或者通過環(huán)境變量ES_JAVA_OPTS
來設(shè)置)菊霜,來強(qiáng)制bootstrap check的執(zhí)行
-
heap size check
如果jvm啟動(dòng)的時(shí)候設(shè)置的初始堆大小和最大堆大小不同,可能會(huì)導(dǎo)致ES運(yùn)行期間的服務(wù)暫停济赎,因?yàn)閖vm堆在系統(tǒng)運(yùn)行期間可能會(huì)改變大小鉴逞。為了避免這種jvm resize導(dǎo)致的ES進(jìn)程暫停,建議啟動(dòng)jvm時(shí)司训,將初始堆大小和最大堆大小設(shè)置的相等构捡。除此之外,如果
bootstrap.memory_lock=true
豁遭,jvm會(huì)在啟動(dòng)期間鎖定jvm的初始大小叭喜。如果要通過heap size check,就必須合理設(shè)置heap size蓖谢。默認(rèn)情況下捂蕴,ES的jvm堆的最小和最大都是1g。如果在生產(chǎn)環(huán)境中使用闪幽,應(yīng)該配置合理的heap size確保ES有足夠的堆內(nèi)存可以使用啥辨。
-
File descriptor check
file descriptor是unix操作系統(tǒng)的一種數(shù)據(jù)結(jié)構(gòu),用來track打開的文件盯腌。在unix操作系統(tǒng)中溉知,所有東西都是file,ES需要大量的file descriptor腕够,比如說每個(gè)shard都由多個(gè)segment和其他文件組成级乍,還有跟其他節(jié)點(diǎn)之間的網(wǎng)絡(luò)通信連接。因?yàn)镋S要使用大量的file descriptor帚湘,所以如果file descriptor耗盡的話玫荣,可能造成事故,例如數(shù)據(jù)丟失大诸。盡量給ES的file descriptor提升到65536捅厂,甚至更高。
GET _nodes/stats/process?filter_path=**.max_file_descriptors
可以用上面這個(gè)請求檢查每個(gè)node上的file descriptor數(shù)量
* soft nofile 65536 * hard nofile 65536
-
memory lock check
如果jvm進(jìn)行一個(gè)major gc的話资柔,那么就會(huì)涉及到heap中的每一個(gè)內(nèi)存頁焙贷,此時(shí)如果任何一個(gè)內(nèi)存頁被swap到了磁盤上,就會(huì)導(dǎo)致很多的磁盤讀寫開銷贿堰,而這些磁盤讀寫開銷如果節(jié)省下來辙芍,可以讓ES服務(wù)更多的請求。有很多方法可以配置系統(tǒng)禁止swap羹与。其中一種方法就是讓jvm去lock heap內(nèi)存在物理內(nèi)存中沸手,設(shè)置
bootstrap.memory_lock=true
即可# 檢查mlockall是否開啟 GET _nodes?filter_path=**.mlockall
-
maximum number of thread check
ES會(huì)將每個(gè)請求拆分成多個(gè)stage外遇,然后將stage分配到不同的線程池中去執(zhí)行。在ES中有多個(gè)線程池來執(zhí)行不同的任務(wù)契吉。所以ES會(huì)創(chuàng)建許多的線程。最大線程數(shù)量的檢查會(huì)確保是說诡渴,ES實(shí)例有權(quán)限去創(chuàng)建足夠的線程捐晶。如果要通過這個(gè)檢查,必須允許ES進(jìn)程能夠創(chuàng)建超過4096個(gè)線程妄辩。
# /etc/security/limits.conf * soft nproc 4096 * hard nproc 4096
-
maximum size virtual memory check
ES使用mmap來將索引映射到ES的address space中惑灵,這可以讓jvm heap外但是內(nèi)存中的索引數(shù)據(jù),可以有非常告訴的讀寫速度眼耀。因此ES需要擁有unlimited address space英支。最大虛擬內(nèi)存大小的檢查,會(huì)要求ES進(jìn)程有unlimited address space
# /etc/security/limits.conf * hard as unlimited
-
max file size check
作為各個(gè)分片的組成部分的segment文件可能會(huì)變得很大(超過幾個(gè)GB)哮伟, 如果ES可以創(chuàng)建的文件的最大大小受到限制的系統(tǒng)上干花,這可能導(dǎo)致寫入失敗。 因此楞黄,最安全的選擇是最大文件大小不受限制池凄,這就是max file size check強(qiáng)制檢查的內(nèi)容
# /etc/security/limits.conf * hard fsize unlimited
-
maximum map count check
要高效使用mmap的話,ES同樣要求創(chuàng)建許多memory-mapped area鬼廓,因此要求linux內(nèi)核允許進(jìn)程擁有至少262144個(gè)memory-mapped area
# /etc/sysctl.conf vm.max_map_count = 262144
-
client jvm check
jvm有兩種模式肿仑,client jvm和server jvm。不同的jvm會(huì)用不同的編譯器來編譯Java源碼碎税,client jvm是用于減少startup time和內(nèi)存占用尤慰,server jvm是用于最大化性能。兩種jvm之間的性能區(qū)別是很明顯的雷蹂。client jvm check會(huì)確保ES沒有運(yùn)行在client jvm下伟端。必須使用server jvm模式來啟動(dòng)es,而server jvm是默認(rèn)的萎河。
-
use serial collector check
針對不同的工作負(fù)載荔泳,jvm提供了不同的垃圾回收器。串行化垃圾回收器對于單cpu機(jī)器或者小內(nèi)存虐杯,是很有效的玛歌。但是對于ES來說,用串行化垃圾回收器擎椰,會(huì)成為一場性能上的災(zāi)難支子。因此這個(gè)check會(huì)確保ES沒有被配置使用串行化垃圾回收器。ES默認(rèn)的就是CMS垃圾回收器达舒。
-
system call filter check
Elasticsearch會(huì)根據(jù)操作系統(tǒng)來安裝各種的system call filter值朋, 安裝這些system call filter是為了防止執(zhí)行與
fork
相關(guān)的system call叹侄,這是Elasticsearch的防御機(jī)制,避免執(zhí)行任何任意代碼昨登,設(shè)置bootstrap.system_call_filter=false
可以禁止此項(xiàng)檢查趾代,后果自負(fù) -
OnError and OnOutOfMemoryError check
jvm參數(shù),OnError和OnOutOfMemoryError允許在jvm遇到了fatal error或者是OutOfMemoryErro的時(shí)候丰辣,執(zhí)行預(yù)定義的命令撒强。但是默認(rèn)情況下,es system call filter是啟用的笙什,這些filter是阻止forking操作的飘哨。因此,用OnError和OnOutOfMemroyError和system call filter是不兼容的琐凭。這個(gè)check會(huì)檢查芽隆,如果啟用了system call filter,還設(shè)置了這兩個(gè)jvm option统屈,那么就不能啟動(dòng)胚吁。所以不要在jvm option中設(shè)置這兩個(gè)參數(shù)。
-
early-access check
jdk提供了一些新版本的早期試用版鸿吆,這些版本不適合用作生產(chǎn)環(huán)境囤采。這個(gè)check會(huì)檢查有沒有使用jdk的e早期試用版,我們應(yīng)該用jdk穩(wěn)定版本惩淳,而不是試用版本
-
G1 GC check
jdk 8的早期版本中的G1 GC蕉毯,有已知的問題可能導(dǎo)致索引破損,在JDK 8u40之前的版本都有這個(gè)問題思犁。這個(gè)check會(huì)檢查是否使用了那種早期的JDk版本代虾。
5. 優(yōu)雅的啟停ES服務(wù)
RPM方式安裝的ES:
- ES服務(wù)開機(jī)自啟動(dòng):
sudo chkconfig --add elasticsearch
# 或者
sudo /bin/systemctl daemon-reload
sudo /bin/systemctl enable elasticsearch.service
- ES服務(wù)啟動(dòng)停止命令:
sudo -i service elasticsearch start
sudo -i service elasticsearch stop
# 或者
sudo systemctl start elasticsearch.service
sudo systemctl stop elasticsearch.service
tar.gz安裝的ES:
啟動(dòng)停止命令:
# 啟動(dòng)
./bin/elasticsearch -d -p pid
# 可以在啟動(dòng)時(shí)進(jìn)行配置
./bin/elasticsearch -d -p pid -Ekey=/etc/elasticsearch
# 停止
# 查詢ES進(jìn)程pid方法一
jps | grep Elasticsearch
14542 Elasticsearch
# 查詢ES進(jìn)程pid方法二
$ ./bin/elasticsearch -p /tmp/elasticsearch-pid -d
$ cat /tmp/elasticsearch-pid && echo
15516
# 停止服務(wù)
kill -SIGTERM 15516
ES服務(wù)異常掛掉的狀態(tài)碼:
JVM internal error 128
Out of memory error 127
Stack overflow error 126
Unknown virtual machine error 125
Serious I/O error 124
Unknown fatal error 1