1. 程式人生 > >Elasticsearch Java虛擬機器配置詳解

Elasticsearch Java虛擬機器配置詳解

ElasticSearch是一個基於Lucene構建的開源,分散式,RESTful搜尋引擎。設計用於雲端計算中,能夠達到實時搜尋,穩定,可靠,快速,安裝使用方便。支援通過HTTP使用JSON進行資料索引。 

  我們建立一個網站或應用程式,並要新增搜尋功能,令我們受打擊的是:搜尋工作是很難的。我們希望我們的搜尋解決方案要快,我們希望 有一個零配置和一個完全免費的搜尋模式,我們希望能夠簡單地使用JSON通過HTTP的索引資料,我們希望我們的搜尋伺服器始終可用,我們希望能夠一臺開 始並擴充套件到數百,我們要實時搜尋,我們要簡單的多租戶,我們希望建立一個雲的解決方案。Elasticsearch旨在解決所有這些問題和更多的。

安裝

  以windows作業系統和ES0.19.7版本為例:

  ①下載elasticsearch-0.19.7.zip

  ②直接解壓至某目錄,設定該目錄為ES_HOME環境變數

  ③安裝JDK,並設定JAVA_HOME環境變數

  ④在windows下,執行 %ES_HOME%\bin\elasticsearch.bat即可執行

分散式搜尋elasticsearch單機與伺服器環境搭建

      先到http://www.elasticsearch.org/download/下 載最新版的elasticsearch執行包,本文寫時最新的是0.19.1,作者是個很勤快的人,es的更新很頻繁,bug修復得很快。下載完解開有三 個包:bin是執行的指令碼,config是設定檔案,lib是放依賴的包。如果你要裝外掛的話就要多新建一個plugins的資料夾,把外掛放到這個檔案 夾中。

1.單機環境:

單機版的elasticsearch執行很簡單,linux下直接 bin/elasticsearch就運行了,windows執行bin/elasticsearch.bat。如果是在區域網中執行elasticsearch叢集也是很簡單的,只要cluster.name設定一致,並且機器在同一網段下,啟動的es會自動發現對方,組成叢集。

2.伺服器環境:

如果是在伺服器上就可以使用elasticsearch-servicewrapper這個es外掛,它支援通過引數,指定是在後臺或前臺執行es,並且支援啟動,停止,重啟es服務(預設es指令碼只能通過ctrl+c關閉es)。使用方法是到https://github.com/elasticsearch/elasticsearch-servicewrapper

下載service資料夾,放到es的bin目錄下。下面是命令集合:
bin/service/elasticsearch +
console 在前臺執行es
start 在後臺執行es
stop 停止es
install 使es作為服務在伺服器啟動時自動啟動
remove 取消啟動時自動啟動

在service目錄下有個elasticsearch.conf配置檔案,主要是設定一些java執行環境引數,其中比較重要的是下面的

引數:

#es的home路徑,不用用預設值就可以
set.default.ES_HOME=<Path to ElasticSearch Home>

#分配給es的最小記憶體
set.default.ES_MIN_MEM=256

#分配給es的最大記憶體
set.default.ES_MAX_MEM=1024


# 啟動等待超時時間(以秒為單位)
wrapper.startup.timeout=300

# 關閉等待超時時間(以秒為單位)

wrapper.shutdown.timeout=300

# ping超時時間(以秒為單位)

wrapper.ping.timeout=300

安裝外掛

  以head外掛為例:

  聯網時,直接執行%ES_HOME%\bin\plugin -install mobz/elasticsearch-head

  不聯網時,下載elasticsearch-head的zipball的master包,把內容解壓到%ES_HOME%\plugin\head\_site目錄下,[該外掛為site型別外掛]

  安裝完成,重啟服務,在瀏覽器開啟 http://localhost:9200/_plugin/head/ 即可

ES概念

  cluster

  代表一個叢集,叢集中有多個節點,其中有一個為主節點,這個主節點是可以通過選舉產生的,主從節點是對於叢集內部來說 的。es的一個概念就是去中心化,字面上理解就是無中心節點,這是對於叢集外部來說的,因為從外部來看es叢集,在邏輯上是個整體,你與任何一個節點的通 信和與整個es叢集通訊是等價的。

  shards

  代表索引分片,es可以把一個完整的索引分成多個分片,這樣的好處是可以把一個大的索引拆分成多個,分佈到不同的節點上。構成分散式搜尋。分片的數量只能在索引建立前指定,並且索引建立後不能更改。

  replicas

  代表索引副本,es可以設定多個索引的副本,副本的作用一是提高系統的容錯性,當個某個節點某個分片損壞或丟失時可以從副本中恢復。二是提高es的查詢效率,es會自動對搜尋請求進行負載均衡。

  recovery

  代表資料恢復或叫資料重新分佈,es在有節點加入或退出時會根據機器的負載對索引分片進行重新分配,掛掉的節點重新啟動時也會進行資料恢復。

  river

  代表es的一個數據源,也是其它儲存方式(如:資料庫)同步資料到es的一個方法。它是以外掛方式存在的一個es服 務,通過讀取river中的資料並把它索引到es中,官方的river有couchDB的,RabbitMQ的,Twitter的,Wikipedia 的。

  gateway

  代表es索引的持久化儲存方式,es預設是先把索引存放到記憶體中,當記憶體滿了時再持久化到硬碟。當這個es叢集關閉再 重新啟動時就會從gateway中讀取索引資料。es支援多種型別的gateway,有本地檔案系統(預設),分散式檔案系統,Hadoop的HDFS和 amazon的s3雲端儲存服務。

  discovery.zen

  代表es的自動發現節點機制,es是一個基於p2p的系統,它先通過廣播尋找存在的節點,再通過多播協議來進行節點之間的通訊,同時也支援點對點的互動。

  Transport

  代表es內部節點或叢集與客戶端的互動方式,預設內部是使用tcp協議進行互動,同時它支援http協議(json格式)、thrift、servlet、memcached、zeroMQ等的傳輸協議(通過外掛方式整合)。

分散式搜尋elasticsearch中文分詞整合

elasticsearch官方只提供smartcn這個中文分詞外掛,效果不是很好,好在國內有medcl大神(國內最早研究es的人之一)寫的兩個中文分詞外掛,一個是ik的,一個是mmseg的,下面分別介紹下兩者的用法,其實都差不多的,先安裝外掛,命令列:
安裝ik外掛:

plugin -install medcl/elasticsearch-analysis-ik/1.1.0  

下載ik相關配置詞典檔案到config目錄

  1. cd config  
  2. wget http://github.com/downloads/medcl/elasticsearch-analysis-ik/ik.zip --no-check-certificate  
  3. unzip ik.zip  
  4. rm ik.zip  

安裝mmseg外掛:

  1. bin/plugin -install medcl/elasticsearch-analysis-mmseg/1.1.0  

下載相關配置詞典檔案到config目錄

  1. cd config  
  2. wget http://github.com/downloads/medcl/elasticsearch-analysis-mmseg/mmseg.zip --no-check-certificate  
  3. unzip mmseg.zip  
  4. rm mmseg.zip  

分詞配置

ik分詞配置,在elasticsearch.yml檔案中加上

  1. index:  
  2.   analysis:                     
  3.     analyzer:        
  4.       ik:  
  5.           alias: [ik_analyzer]  
  6.           type: org.elasticsearch.index.analysis.IkAnalyzerProvider  

  1. index.analysis.analyzer.ik.type : “ik”  

這兩句的意義相同
mmseg分詞配置,也是在在elasticsearch.yml檔案中

  1. index:  
  2.   analysis:  
  3.     analyzer:  
  4.       mmseg:  
  5.           alias: [news_analyzer, mmseg_analyzer]  
  6.           type: org.elasticsearch.index.analysis.MMsegAnalyzerProvider  

  1. index.analysis.analyzer.default.type : "mmseg"  

mmseg分詞還有些更加個性化的引數設定如下

  1. index:  
  2.   analysis:  
  3.     tokenizer:  
  4.       mmseg_maxword:  
  5.           type: mmseg  
  6.           seg_type: "max_word"  
  7.       mmseg_complex:  
  8.           type: mmseg  
  9.           seg_type: "complex"  
  10.       mmseg_simple:  
  11.           type: mmseg  
  12.           seg_type: "simple"  

這樣配置完後外掛安裝完成,啟動es就會載入外掛。

定義mapping

在新增索引的mapping時就可以這樣定義分詞器

  1. {  
  2.    "page":{  
  3.       "properties":{  
  4.          "title":{  
  5.             "type":"string",  
  6.             "indexAnalyzer":"ik",  
  7.             "searchAnalyzer":"ik"  
  8.          },  
  9.          "content":{  
  10.             "type":"string",  
  11.             "indexAnalyzer":"ik",  
  12.             "searchAnalyzer":"ik"  
  13.          }  
  14.       }  
  15.    }  
  16. }  

indexAnalyzer為索引時使用的分詞器,searchAnalyzer為搜尋時使用的分詞器。

java mapping程式碼如下:

  1. XContentBuilder content = XContentFactory.jsonBuilder().startObject()  
  2.         .startObject("page")  
  3.           .startObject("properties")         
  4.             .startObject("title")  
  5.               .field("type", "string")             
  6.               .field("indexAnalyzer", "ik")  
  7.               .field("searchAnalyzer", "ik")  
  8.             .endObject()   
  9.             .startObject("code")  
  10.               .field("type", "string")           
  11.               .field("indexAnalyzer", "ik")  
  12.               .field("searchAnalyzer", "ik")  
  13.             .endObject()       
  14.           .endObject()  
  15.          .endObject()  
  16.        .endObject()  

定義完後操作索引就會以指定的分詞器來進行分詞。

 附:

elasticsearch的基本用法


最大的特點: 
1. 資料庫的 database, 就是  index 
2. 資料庫的 table,  就是 tag 
3. 不要使用browser, 使用curl來進行客戶端操作.  否則會出現 java heap ooxx... 

curl:  -X 後面跟 RESTful :  GET, POST ... 
-d 後面跟資料。 (d = data to send) 

1. create:  

指定 ID 來建立新記錄。 (貌似PUT, POST都可以) 
$ curl -XPOST localhost:9200/films/md/2 -d ' 
{ "name":"hei yi ren", "tag": "good"}' 

使用自動生成的 ID 建立新紀錄: 
$ curl -XPOST localhost:9200/films/md -d ' 
{ "name":"ma da jia si jia3", "tag": "good"}' 

2. 查詢: 
2.1 查詢所有的 index, type: 
$ curl localhost:9200/_search?pretty=true 

2.2 查詢某個index下所有的type: 
$ curl localhost:9200/films/_search 

2.3 查詢某個index 下, 某個 type下所有的記錄: 
$ curl localhost:9200/films/md/_search?pretty=true 

2.4 帶有引數的查詢:  
$ curl localhost:9200/films/md/_search?q=tag:good 
{"took":7,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":2,"max_score":1.0,"hits":[{"_index":"film","_type":"md","_id":"2","_score":1.0, "_source" : 
{ "name":"hei yi ren", "tag": "good"}},{"_index":"film","_type":"md","_id":"1","_score":0.30685282, "_source" : 
{ "name":"ma da jia si jia", "tag": "good"}}]}} 

2.5 使用JSON引數的查詢: (注意 query 和 term 關鍵字) 
$ curl localhost:9200/film/_search -d ' 
{"query" : { "term": { "tag":"bad"}}}' 

3. update  
$ curl -XPUT localhost:9200/films/md/1 -d { ...(data)... } 

4. 刪除。 刪除所有的: 
$ curl -XDELETE localhost:9200/films

引言:

今天,事情終於發生了。Java6(Mustang),是2006年早些時候出來的,至今仍然應用在眾多生產環境中,現在終於走到了盡頭。已經沒有什麼理由阻止遷移到Java7(Dolphin)上了。

這也促使我想寫一篇關於在ElasticSearch上配置Java6和7的細微差異的博文。

Elasticsearch對Java虛擬機器進行了預先的配置。通常情況下,因為這些配置的選擇還是很謹慎的,所以你不需要太關心,並且你能立刻使用ElasticSearch。

但是,當你監視ElasticSearch節點記憶體時,你可能嘗試修改一些配置。這些修改是否會改善你的處境?

這篇博文嘗試揭開Elasticsearch配置的神祕面紗,並且討論最常見的調整。最終,會給出一些推薦的配置調整。

Elasticsearch JVM 配置概覽:

這些是Elasticsearch 0.19.11版本的預設配置。

JVM引數 Elasticsearch預設值 Environment變數
-Xms 256m ES_MIN_MEM
-Xmx 1g ES_MAX_MEM
-Xms and -Xmx ES_HEAP_SIZE
-Xmn ES_HEAP_NEWSIZE
-XX:MaxDirectMemorySize ES_DIRECT_SIZE
-Xss 256k
-XX:UseParNewGC +
-XX:UseConcMarkSweepGC +
-XX:CMSInitiatingOccupancyFraction 75
-XX:UseCMSInitiatingOccupancyOnly +
-XX:UseCondCardMark (commented out)

首先你注意到的是,Elasticsearch預留了256M到1GB的堆記憶體。

這個設定適用於開發和演示環境。開發人員只需要簡單的解壓發行包,再執行./bin/elasticsearch -f就完成了Elasticsearch的安裝。當然這點對於開發來說非常棒,並且在很多場景下都能工作,但是當你需要更多記憶體來降低Elasticsearch負載的時候就不行了,你需要比2GB RAM更多的可用記憶體。

ES_MIN_MEM/ES_MAX_MEM是控制堆大小的配置。新的ES_HEAP_SIZE變數是一個更為便利的選擇,因為將堆的初始大小和最大值設為相同。也推薦在分配堆記憶體時儘可能不要用記憶體的碎片。記憶體碎片對於效能優化來說非常不利。

ES_HEAP_NEWSIZE是可選引數,它控制堆的子集大小,也就是新生代的大小。

ES_DIRECT_SIZE控制本機直接記憶體大小,即JVM管理NIO框架中使用的資料區域大小。本機直接記憶體可以被對映到虛擬地址空間上,這樣在64位的機器上更高效,因為可以規避檔案系統緩衝。Elasticsearch對本機直接記憶體沒有限制(可能導致OOM)。

由於歷史原因Java虛擬機器有多個垃圾收集器。可以通過以下的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)

UseParNewGCUseConcMarkSweepGC組合啟用垃圾收集器的併發多執行緒模式。UseConcMarkSweepGC自動選擇UseParNewGC模式並禁用序列收集器(Serial collector)。在Java6中這是預設行為。

CMSInitiatingOccupancyFraction提煉了一種CMS(Concurrent-Mark-Sweep)垃圾收集設定;它將舊生代觸發垃圾收集的閥值設為75.舊生代的大小是堆大小減去新生代大小。這告訴JVM當堆內容達到75%時啟用垃圾收集。這是個估計的值,因為越小的堆可能需要越早啟動GC。

UseCondCardMark將在垃圾收集器的card table使用時,在marking之前進行額外的判斷,避免冗餘的store操作。UseCondCardMark不影響Garbage-First收集器。強烈推薦在高併發場景下配置這個引數(規避card table marking技術在高併發場景下的降低吞吐量的負面作用)。在ElasticSearch中,這個引數是被註釋掉的。

有些配置可以參考諸如Apache Cassandra專案,他們在JVM上有類似的需求。

總而言之,ElastciSearch配置上推薦:

1. 不採用自動的堆記憶體配置,將堆大小預設最大值設為1GB

2.調整觸發垃圾收集的閥值,比如將gc設為75%堆大小的時候觸發,這樣不會影響效能。

3.禁用Java7預設的G1收集器,前提是你的ElasticSearch跑在Java7u4以上的版本上。

JVM程序的記憶體結果

JVM記憶體由幾部分組成:

Java程式碼本身:包括內部程式碼、資料、介面,除錯和監控代理或者位元組碼指令

非堆記憶體:用於載入類

棧記憶體:用於為每個執行緒儲存本地變數和運算元

堆記憶體:用於存放物件引用和物件本身

直接緩衝區:用於緩衝I/O資料

堆記憶體的大小設定非常重要,因為Java的執行依賴於合理的堆大小,並且JVM需要從作業系統那獲取有限的堆記憶體,用於支撐整個JVM生命週期。

如果堆太小,垃圾回收就會頻繁發生,發生OOM的機率會很大。

如果堆太大,垃圾回收會延遲,但是一旦回收,就需要處理大量的存活堆資料。並且,作業系統的壓力也會變大,因為JVM程序需要更大的堆,產生換頁的可能性就會提高。

注意,使用CMS垃圾收集器,Java不會把記憶體還給作業系統,因此配置合理的堆初始值和最大值就非常重要。

非堆記憶體由Java應用自動分配。沒有什麼引數控制這裡的大小,這是由Java應用程式程式碼自己決定的。

棧記憶體在每個執行緒中分配,在Elasticsearch中,每個執行緒大小必須由128K增加到256K,因為Java7比Java6需要更大的棧記憶體 ,這是由於Java7支援新的程式語言特徵來利用棧空間。比如,引入了continuations模型,程式語言的一個著名概念。Continuations模型對於

協同程式、綠色執行緒(green thread)、纖程(fiber)非常有用 。當實現非阻塞I/O時,一個大的優勢是,程式碼可以根據執行緒實際使用情況編寫,但是執行時仍然在後臺採用非阻塞I/O。Elasticsearch使用了多個執行緒池,因為Netty I/O框架和Guava是Elasticsearch的基礎元件,因此在用Java7時,可以考慮進一步挖掘優化執行緒的特性。

發揮增加棧空間大小的優勢還是有挑戰的,因為不同的作業系統、不同的CPU架構,甚至在不同的JVM版本之間,棧空間的消耗不是容易比較的。取決於CPU架構和作業系統,JVM的棧空間大小是內建的。他們是否在所有場景下都適合?例如Sloaris Sparc 64位的JVM Xss預設為512K,因為有更大地址指標,Sloaris X86為320K。Linux降為256K。Windows 32位Java6預設320K,Windows 64位則為1024K。

大堆的挑戰

今天,幾GB的記憶體是很常見的。但是在不久以前,系統管理員還在為多幾G的記憶體需求淚流滿面。

Java垃圾收集器是隨著2006年的Java6的出現而顯著改進的。從那以後,可以併發執行多工,並且減少了GC停頓機率: stop - the - world階段。CMS演算法是革命性的,多工,併發, 不需要移動的GC。但是不幸的是,對於堆的存活資料量來說,它是不可擴充套件的。Prateek Khanna 和 Aaron Morton給出了CMS垃圾收集器能夠處理的堆規模的數字。

避免Stop-the-world階段

我們已經學習了Elasticsearch如何配置CMS垃圾收集器。但這並不能組織長時間的GC停頓,它只是降低了發生的機率。CMS是一個低停頓機率的收集器,但是仍然有一些邊界情況。當堆上有MB級別的大陣列,或者其他一些特殊的場景,CMS可能比預期要花費更多的時間。

MB級別陣列的建立在Lucene segment-based索引合併時是很常見的。如果你希望降低CMS的額外負載,就需要調整Lucene合併階段的段數量,使用引數index.merge.policy.segments_per_tier

減少換頁

大堆的風險在於記憶體壓力上。注意,如果Java JVM在處理大堆時,這部分記憶體對於系統其它部分來說是不可用的。如果記憶體吃緊,作業系統會進行換頁,並且,在緊急情況下,當所有其他方式回收記憶體都失敗時,會強制殺掉程序。如果換頁發生,整個系統的效能會下降,自然GC的效能也跟著下降。所以,不要給堆分配太多的記憶體。

垃圾收集器的選擇

從Java JDK 7u4開始,Garbage-First(G1)收集器是Java7預設的垃圾收集器。它適用於多核的機器以及大記憶體。它一方面降低了停頓時間,另一方面增加了停頓的次數。整個堆的操作,例如全域性標記,是在應用執行緒中併發執行的。這會防止隨著堆或存活資料大小的變化,中斷時間也成比例的變化。

G1收集器目標是獲取更高的吞吐量,而不是速度。在以下情況下,它能執行的很好:

1. 存活資料佔用了超過50%的Java堆

2. 物件分配比例或者promotion會有明顯的變化

3. 不希望gc或者compaction停頓時間長(超過0.5至1s)

注意,如果使用G1垃圾收集器,堆不再使用的記憶體可能會被歸還給作業系統

G1垃圾收集器的不足是CPU使用率越高,應用效能越差。因此,如果在記憶體足夠和CPU能力一般的情況下,CMS可能更勝一籌。

對於Elasticsearch來說,G1意味著沒有長時間的stop-the-world階段,以及更靈活的記憶體管理,因為buffer memory和系統I/O快取能更充分的利用機器記憶體資源。代價就是小成本的最大化效能,因為G1利用了更多CPU資源。

效能調優策略

你讀這篇博文因為你希望在效能調優上得到一些啟示:

1. 清楚瞭解你的效能目標。你希望最大化速度,還是最大化吞吐量?

2. 記錄任何事情(log everything),收集統計資料,閱讀日誌、分析事件來診斷配置

3. 選擇你調整的目標(最大化效能還是最大化吞吐量)

4. 計劃你的調整

5. 應用你的新配置

6. 監控新配置後的系統

7. 如果新配置沒有改善你的處境,重複上面的一系列動作,反覆嘗試

Elasticsearch垃圾收集日誌格式

Elasticsearch長時間GC下warns級別的日誌如下所示:

[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]}

JvmMonitorService類中有相關的使用方式:

Logfile Explanation
gc 執行中的gc
ParNew new parallel garbage collector
duration 2.6m gc時間為2.6分鐘
collections [1]/[2.7m] 在跑一個收集,共花2.7分鐘
memory [2.4gb]->[2.3gb]/[3.8gb] 記憶體消耗, 開始是2.4gb, 現在是2.3gb, 共有3.8gb記憶體
Code Cache [13.7mb]->[13.7mb]/[48mb] code cache佔用記憶體
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佔用記憶體

JvmMonitorSer

一些建議

1. 不要在Java 6u22之前的釋出版本中跑Elasticsearch。有記憶體方面的bug。那些超過兩三年的bug和缺陷會妨礙Elasticsearch的正常執行。與舊的OpenJDK 6相比,更推薦Sun/Oracle的版本,因為後者修復了很多bug。

2. 放棄Java6,轉到Java7。Oracle宣稱Java6更新到2013年2月結束。考慮到Elasticsearch還是一個相對新的軟體,應該使用更新的技術來提升效能。儘量從JVM中擠壓效能。檢查作業系統的版本。在最新版本的作業系統中執行,有助於你的Java執行環境達到最佳效能。

3. 定期更新Java執行環境。平均一個季度一次。告訴sa你需要及時更新Java版本,以獲取Java效能的提升。

4. 從小到大。先在Elasticsearch單節點上進行開發。但是不要忘了Elasticsearch分散式的強大功能。單節點不能模擬生產環境的特徵,至少需要3個節點進行開發測試。

5. 在調整JVM之前先做一下效能測試。對你的系統建立效能基線。調整測試時候的節點數量。如果索引時候負載很高,你可能需要降低Elasticsearch索引時候佔用的堆大小,通過index.merge.policy.segments_per_tierparameter引數調整段的合併。

6. 調整前清楚你的效能目標,然後決定是調整速度還是吞吐量。

7. 啟用日誌以便更好的進行診斷。在優化系統前進行小心的評估。

8. 如果使用CMS垃圾收集器,你可能需要加上合理的 -XX:CMSWaitDuration 引數。

9. 如果你的堆超過6-8GB,超過了CMS垃圾收集器設計容量,你會遇到長時間的stop-the-world階段,你有幾個方案:調整CMSInitiatingOccupancyFraction引數降低長時間GC的機率減少最大堆的大小;啟用G1垃圾收集器。

10. 學習垃圾收集調優藝術。如果你想精通的話,列出可用的JVM選項,在java命令中加入java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version,然後調優。