原文鏈接:
http://jprante.github.com/2012/11/28/Elasticsearch-Java-Virtual-Machine-settings-explained.html
從2006年的java6 到現在java7無論是性能或其它方面都有了很大的改進,我們沒有理由不在使用Java7,我個人也認為java7在內存方面比java6優秀.
這使我有對java6和java7及es在jvm設置有了很大的趣興,因此寫一篇博文一探其中之道。
Es已經預先為我們的JVM進行了一些設置,而且這些設置都是比較好的,現在這方面的設置也非常小心,因此你不需要關心jvm的設置就可以馬上使用ES,這大概就是所謂的開箱即使吧。
但我們也可能jvm進行一些自己的設置,以使其能被監測或是改善你的ES Cluster中的node的一些性能。
這篇博文試圖闡明ES中的預配置和討論最常見的一些調整,最后給出如何進行調優。
ES JVM 設置
JVM參數 |
ES默認值 |
環境變量名 |
||
-Xms |
256m |
|
||
-Xmx |
1g |
|
||
-Xms and –Xmx |
|
|
||
-Xmn |
|
|
||
-XX:MaxDirectMemorySize |
|
|
||
-Xss |
256k |
|
||
-XX:UseParNewGC |
+ |
|
||
-XX:UseConcMarkSweepGC |
+ |
|
||
|
75 |
|
||
-XX:UseCMSInitiatingOccupancyOnly |
|
|
||
-XX:UseCondCardMark |
|
|
我們可以注意到ES JVM Heap內存設置為在256M在1GB之間.
這個設置是為在開發和示范環境中使用的,開發人員可以通過簡單地安裝ES就可以使用了,但是這樣的內存設置在很多情況下都是不夠用的,我在需要設置更大的值。
(JVM)
ES_MIN_MEM/ES_MAX_MEM 用於控制jvm的堆內存,另外還有ES_HEAP_SEIZ,這樣我可以設置更多的堆內存用於ES,另外建議不在啟動內存堆平衡,因為這樣會浪費很大的性能。
ES_HEAP_NEWSIZE這個參數用於控制堆內存的子集,即新生代堆控制
ES_DIRECT_SIZE,我們可以對應到Direct Memory Size這個參數,在JVM管理數據中使用的是NIO,本機內存可以映射到虛擬地址空間,在X64的架構上更有效,在ES中沒有選擇進行設置,但是有一個問題,本機直接內存的分配不會受到Java堆大小的限制,但是即然是內存那肯定還是要受到本機物理內存(包括SWAP區或者Windows虛擬內存)的限制的,一般服務器管理員配置JVM參數時,會根據實際內存設置-Xmx等參數信息,但經常忽略掉直接內存,使得各個內存區域總和大於物理內存限制(包括物理的和操作系統級的限制),而導致動態擴展時出現OutOfMemoryError異常。
下面例出一些JVM參數設置
JVM parameter Garbage collector
-XX:+UseSerialGC serial collector
-XX:+UseParallelGC parallel collector
-XX:+UseParallelOldGC Parallel compacting collector
-XX:+UseConcMarkSweepGC Concurrent-Mark-Sweep ( CMS ) collector
-XX:+UseG1GC Garbage-First collector (G1)
UseParNewGC和UseConcMarkSweepGC是結並並行和行發性的垃圾回收機制,在JAVA6中將默認為UserParNewGC和UseGoncMarkSweepGC並禁用串行收集器.
CMSInitiatingOccupancyFraction 垃圾回收,這個75是指,到heap占用到75%時開發進行清理,我們知道堆分為新生代和老年代兩塊可新生代一塊為老年代的兩倍,也許在沒有達到75%時也可能進行垃圾回收。
UseCondCardMark 將在在高度並發的情況下,將些值注釋掉
總結:
1、修改MAX 和MIN Heap大小設置。
2、設置垃圾回收百分比
3、如果在JAVA7中禁用默認的G1垃圾回收機制。
JVM進程的內存結構
JVM內存分為如下幾段:
JVM CODE用於內部代碼存放
Noe-heap memory用於加載類
Stack memory 用於存放本地變量和線程操作數
Heap memory 存放引用類型對象
Direct Buffer,緩沖輸入,輸出數據
Heap memory大小設置是非常重要的,因為java的運行取決於一個合理的heap的大小,如果設置太小,在許多垃圾回收或是高性能的情況下就會出現OutOfMemory異常。如果堆太大,垃圾回收將需要更大的數據,該算法將要面對更高數量的存活堆,這樣操作系統也會面對較大的壓力。
Non-heap內存分配是由java應用程序自動設置的,沒有辦法控制這個參數,因為它是由JAVA應用程序代碼決定的。
垃圾回收與Lucene段
在ES中的垃圾回收器是集用的CMS垃圾回收,這種回收器不是提高敢回收的效率可是降低了回收的次數,但是面對比較大的數據集合時,這種回收可能需要的時間更長。
而這種大的數據集合主要是在Lucene的索引中,因些可以將索引的段進行一行調優工作,提高GC的效率。
index.merge.policy.segments_per_tier
減少分頁
在大堆內存的情況下,如果內存不足時會與操作系統的SWAP空間進行分頁數據的交換,但是這種交換是非常慢的,這種會降低整體性能。
垃圾回收器的選擇
JAVA 7中的默認是G1垃圾回收器,這種回收器和CMS回收相對,他在於處理吞吐量,但是如果在大堆的情況下CMS回收器在性能上將超過G1.
性能調優策略
1、 收集日志
2、 對日志進行分析
3、 選擇你要優化的目標
4、 計划優化
5、 應用新有設置
6、 監控程序在新設置后的運行情況
7、 反復試嘗
ES 垃圾回收日志格式
將日志等級調用警告在垃圾回收時你能看到如下信息:
[2012-11-26 18:13:53,166][WARN ][monitor.jvm ] [Ectokid] [gc][ParNew][1135087][11248] duration [2.6m], collections [1]/[2.7m], total [2.6m]/[6.8m], memory [2.4gb]->[2.3gb]/[3.8gb], all_pools {[Code Cache] [13.7mb]->[13.7mb]/[48mb]}{[Par Eden Space] [109.6mb]->[15.4mb]/[1gb]}{[Par Survivor Space] [136.5mb]->[0b]/[136.5mb]}{[CMS Old Gen] [2.1gb]->[2.3gb]/[2.6gb]}{[CMS Perm Gen] [35.1mb]->[34.9mb]/[82mb]}
LogFile |
說明 |
Gc |
垃圾回收運行 |
ParNew |
新生代垃圾回收器 |
duration 2.6m |
垃圾回收花費時間 |
collections [1]/[2.7m] |
一個收集器運行花費2.7M |
memory [2.4gb] |
預設2.4GB |
[2.3gb]/[3.8gb] |
現在使用2.3GB/總共3.8GB |
Code Cache [13.7mb]->[13.7mb]/[48mb] |
代碼緩存 |
Par Eden Space [109.6mb]->[15.4mb]/[1gb] |
Par Eden Space使用空間 |
Par Survivor Space[136.5mb]->[0b]/[136.5mb] |
Par Survivor Space |
CMS Old Gen [2.1gb]->[2.3gb]/[2.6gb] |
CMS Old Gen |
CMS Perm Gen [35.1mb]->[34.9mb]/[82mb] |
CMS Perm Gen |
建議:
1、ES不要運行在6U22之前因之多版本的JDK存在許多的bug,盡量使用Sun/Oracle比較最出的JDK6-7因為里面修復很多bug.
如果在JAVA7正式發布的情況下最好使用JDK7(不過要到2013了)
2、考慮到ES是一個比較新的軟件,利用最先的技術來獲取性能,盡量從JVM中來擠壓性能,另外檢索您的操作系統是否是最新版的,盡量使用最新版的操作系統。
3、做好隨時更新JAVA版本和ES的版本的情況,因為每季度或是每年都會有新的版本出來。所以在做好版本更新的准備
4、測試從小到大,因為ES的強在多個節點的部署,一個節點是不足以測試出其性能,一個生產系統至少在三個節點以上。
5、測試JVM
6、如果索引有更新請記住對索引段的操作(index.merge.policy.segments_per_tier)
7、在性能調優之前,請先確定系統的最大性能和最大吞吐量
8、啟用日志記錄對JAVA垃圾回怍機制,有助於更好的診斷,以至於來調整你的系統
9、提高CMS垃圾收集器,您可以添加一個合理的- xx:CMSWaitDuration參數
10、如果堆大小趣過6-8GB,請選擇使用CMS