19.Elasticsearch生產集羣部署之絕對不能隨意調節jvm和thread pool的原因

es中有很多的配置都讓大家忍不住去調優,因爲也許大家都太過於迷戀性能優化了,都認爲優化一些配置可以大幅度提升性能,就感覺性能調優像個魔法一樣,是個萬能的東西。但是其實99.99%的情況下,對於es來說,大部分的參數都保留爲默認的就可以了。因爲這些參數經常被濫用和錯誤的調節,繼而導致嚴重的穩定性問題以及性能的急劇下降。

1、jvm gc

jvm使用垃圾回收器來釋放掉不用的內存,千萬不要去調節默認的垃圾回收行爲。es默認用的垃圾回收器是CMS。CMS回收器是併發式的回收器,能夠跟應用程序工作線程併發工作,最大程度減少垃圾回收時的服務停頓時間。但是CMS還是會有兩個停頓階段,同時在回收特別大的heap時也會有一些問題。儘管有一些缺點,但是CMS對於要求低延時請求響應的軟件來說,還是最佳的垃圾回收器,因此官方的推薦就是使用CMS垃圾回收器。

有一種最新的垃圾回收器叫做G1。G1回收器可以比CMS提供更少的回收停頓時間,而且能夠這對大heap有更好的回收表現。它會將heap劃分爲多個region,然後自動預測哪個region會有最多可以回收的空間。通過回收那些region,就可以最小化停頓時長,而且可以針對大heap進行回收。

聽起來還挺不錯的,但是不幸的是,G1還是比較年輕的一種垃圾回收器,而且經常會發現一些新的bug,這些bug可能會導致jvm掛掉。lucene的測試套件就檢查出來了G1的一些bug。因此es官方不推薦現在使用G1垃圾回收器,也許在不久的未來,等G1更加穩定的時候,可以使用G1。

2、threadpool

每個人都很喜歡去調優線程池,而且大部分人都特別喜歡增加線程池的線程數量,無論是大量的寫入,還是大量的搜索,或者是感覺服務器的cpu idle空閒率太高,都會增加更多的線程。在es中,默認的threadpool設置是非常合理的,對於所有的threadpool來說,除了搜索的線程池,都是線程數量設置的跟cpu core一樣多的。如果我們有8個cpu core,那麼就可以並行運行8個線程。那麼對於大部分的線程池來說,分配8個線程就是最合理的數量。

不過搜索會有一個更加大的threadpool,一般被配置爲:cpu core * 3 / 2 + 1。

也許我們會覺得有些線程可能會因爲磁盤IO等操作block住,所以我們需要更多的線程。但是在es中這並不是一個問題,大多數的磁盤IO操作都是由lucene的線程管理的,而不是由es管理的,因此es的線程不需要關心這個問題。此外,threadpool還會通過在彼此之間傳遞任務來協作執行,我們不需要擔心某一個網絡線程會因爲等待一次磁盤寫操作,而導致自己被block住,無法處理網絡請求。網絡線程可以將那個磁盤寫操作交給其他線程池去執行,然後自己接着回來處理網絡請求。

其實我們的進程的計算能力是有限的,分配更多的線程只會強迫cpu在多個線程上下文之間頻繁來回切換。一個cpu core在同一時間只能運行一條線程,所以如果cpu要切換到另外一個線程去執行,需要將當前的state保存起來,然後加載其他的線程進來執行。如果線程上下文切換髮生在一個cpu core內,那麼還好一些,但是如果在多個cpu core之間發生線程上下文切換,那麼還需要走一個cpu core內部的通信。這種線程上下文切換會消耗掉很多的cpu資源,對於現在的cpu來說,每次線程上下文切換,都會導致30微秒的時間開銷,所以寧願將這些時間花費在任務的處理上。

很多人會將threadpool大小設置爲一些很愚蠢的數值,在一個8核的機器上,可能運行了超過60,100,甚至1000個線程。這麼多的線程會導致cpu資源利用率很低。所以下次如果我們要調節線程池的話,記住,千萬別這麼幹。如果一定要調節線程數量,也得記住要根據你的cpu core數量來調節,比如設置爲cpu core的兩倍,如果設置的再多,那麼就是一種浪費了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章