原文連結:
從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的效率。
減少分頁
在大堆記憶體的情況下,如果記憶體不足時會與作業系統的SWAP空間進行分頁資料的交換,但是這種交換是非常慢的,這種會降低整體性能。
垃圾回收器的選擇
Java 7中的預設是G1垃圾回收器,這種回收器和CMS回收相對,他在于處理吞吐量,但是如果在大堆的情況下CMS回收器在性能上将超過G1.
性能調優政策
1、 收集日志
2、 對日志進行分析
3、 選擇你要優化的目标
4、 計劃優化
5、 應用新有設定
6、 監控程式在新設定後的運作情況
7、 反複試嘗
ES 垃圾回收日志格式
将日志等級調用警告在垃圾回收時你能看到如下資訊:
[2012-11-26 18:13:53,166][WARN ][ ] [Ectokid] [gc][ParNew][1135087][11248] duration [], collections [1]/[], total []/[], memory []->[]/[],
all_pools {[Code Cache] []->[]/[48mb]}{[Par Eden Space] []->[]/[1gb]}{[Par Survivor Space] []->[0b]/[]}{[CMS Old Gen] []->[]/[]}{[CMS Perm Gen] []->[]/[82mb]}
LogFile | 說明 |
Gc | 垃圾回收運作 |
ParNew | 新生代垃圾回收器 |
duration | 垃圾回收花費時間 |
collections [1]/[] | 一個收集器運作花費2.7M |
memory [] | 預設 |
[]/[] | 現在使用總共3.8GB |
Code Cache []->[]/[48mb] | 代碼緩存 |
Par Eden Space []->[]/[1gb] | Par Eden Space使用空間 |
Par Survivor Space[]->[0b]/[] | Par Survivor Space |
CMS Old Gen []->[]/[] | CMS Old Gen |
CMS Perm Gen []->[]/[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、如果索引有更新請記住對索引段的操作()
7、在性能調優之前,請先确定系統的最大性能和最大吞吐量
8、啟用日志記錄對JAVA垃圾回怍機制,有助于更好的診斷,以至于來調整你的系統
9、提高CMS垃圾收集器,您可以添加一個合理的- xx:CMSWaitDuration參數
10、如果堆大小趣過6-8GB,請選擇使用CMS