Alibaba Dragonwell 8 介紹
Alibaba Dragonwell 8 是一款免費的 OpenJDK 發行版。它提供長期支援,包括效能增強和安全修復。Alibaba Dragonwell 8 目前支援 X86-64/Linux 平臺,在資料中心大規模 Java 應用部署情況下, 可以大幅度提高穩定性、效率以及效能。Alibaba Dragonwell 8 是 OpenJDK 的下游(friendly fork),使用了和 OpenJDK 一樣的 licensing。Alibaba Dragonwell 8 與 Java SE 標準相容,使用者可以使用 Alibaba Dragonwell 8 開發和執行 Java 應用程式。此次開源的 Alibaba Dragonwell 8 是阿里巴巴內部 OpenJDK 定製版 AJDK 的開源版本, AJDK 為線上電商,金融,物流做了結合業務場景的優化,執行在超大規模的,100,000+ 伺服器的阿里巴巴資料中心。
安裝 Alibaba Dragonwell 8
目前 Alibaba Dragonwell 8 只支援 Linux x86-64 平臺,並且提供了二進位制的預編譯 JDK 包,您可以通過下面的簡單兩步安裝 Alibaba Dragonwell 8。
- 從 Github 上面 Alibaba Dragonwell 8 專案的下載頁面下載預編譯的二進位制 JDK 包。
下載頁面連結 github.com/alibaba/dra… - 將下載下來的 tar 包解壓到目標安裝目錄即可。
安裝完畢後,只需要將應用引用 的 JAVA_HOME 指向 Alibaba Dragonwell 8 的安裝目錄就可以使用了。我們以Tomcat8.5.39 版本為例,為了讓 Tomcat 執行在 Alibaba Dragonwell 8上面,只需要在啟動Tomcat時使用如下命令:
JAVA_HOME=/path/to/dragonwell8/installation sh tomcat/bin/catalina.sh start複製程式碼
為了確認是執行在 Alibaba Dragonwell 8上面,可以進一步通過給 java 命令新增 -showversion
引數來列印 JDK 版本資訊加以判斷。
JAVA_HOME=/path/to/dragonwell8/installation JAVA_OPTS="-showversion" sh tomcat/bin/catalina.sh start複製程式碼
啟動完畢後在 tomcat/logs/catalina.out 檔案的開頭,可以看到 Alibaba Dragonwell 8 的版本資訊
使用 Alibaba Dragonwell 8 專有特性
在 8.0-preview 這個版本中, Alibaba Dragonwell 8 提供了兩個在阿里巴巴的生產環境中進行過廣泛驗證的特性:JWarmUp 和 Java Flight Recorder。這兩個特性都已經在上游 OpenJDK 社群提交了 JEP 或 patch,在上游合併完成之前,我們希望讓 Alibaba Dragonwell 8 的使用者可以提前使用到這兩個特性。
JWarmUp 快速預熱 Java 應用
OpenJDK 使用了 JIT(Just-in-time) 即時編譯技術,可以動態的把 Java 位元組碼編譯成高度優化過機器碼,提高執行效率,但在編譯之前,Java 程式碼是以相對低效的直譯器模式執行的。
在應用啟動完成後、業務流量剛進來的短時間內,容易出現的狀況是大量 Java 方法開始被 JIT 編譯,同時業務請求被較慢的直譯器模式執行,最終的結果就是系統負載飆高,可能導致很多使用者請求超時。為了解決這個問題,之前的很多做法是使用模擬流量來提前預熱應用,JWarmUp 特性提供了一個新的選擇,就是利用 Java 虛擬機器前一次執行編譯得記錄來預熱本次應用的執行。
JWarmUp 的原理如下圖所示:
一個典型的應用場景是當應用需要釋出新版本的時候,
- 首先 JWarmUp 在 Beta 環境(或者有著和生產環境類似流量的其他場景)的單臺機器上短時間執行 Java 應用,並記錄、收集這段時間裡面 JIT 編譯器所做動作的一些後設資料。
- 然後會把這些後設資料複製到生產環境的每一臺包含了新版本程式碼的機器/容器裡面。
- 最後在生產環境機器中通過 JWarmUp 引數載入 beta 環境生成的後設資料,來指導生產環境的機器在啟動應用的過程中就完成 JIT 預熱。
這樣當使用者請求進入的時候,應用就會處於效能最高的峰值狀態。
收集預熱資料
還以 Tomcat 應用為例,可以新增下面的命令列引數來在 beta 環境中收集 JIT 編譯時生成的後設資料,其中引數 -XX:CompilationWarmUpLogfile=
指定的就是生成的 JWarmUp 檔案的路徑。
JAVA_HOME=/path/to/dragonwell8/installation JAVA_OPTS="-XX:ReservedCodeCacheSize=512m -XX:CompilationWarmUpLogfile=$PWD/jwarmup.log -XX:+CompilationWarmUpRecording -XX:+CompilationWarmUp -XX:-TieredCompilation -XX:+DeoptimizeBeforeWarmUp -XX:CompilationWarmUpDeoptTime=30 -XX:+PrintCompilationWarmUpDetail" sh bin/catalina.sh start複製程式碼
生成之後可以把這個檔案通過 OSS、SFTP 等方式傳輸到生產環境的機器上。
使用記錄的資料來預熱 Java 應用
在生產環境的機器上,只需要使用下面的引數,就可以利用之前的預熱資料來啟動一個新的 Tomcat 例項,其中引數 -XX:CompilationWarmUpLogfile=
制定的就是需要被載入的 JWarmUp 檔案路徑,這個檔案應該是上一步收集預熱資料時從 beta 環境複製過來的。
JAVA_HOME=/path/to/dragonwell8/installation JAVA_OPTS="-XX:ReservedCodeCacheSize=512m -XX:CompilationWarmUpLogfile=$PWD/jwarmup.log -XX:+CompilationWarmUp -XX:-TieredCompilation -XX:+DeoptimizeBeforeWarmUp -XX:CompilationWarmUpDeoptTime=30 -XX:+PrintCompilationWarmUpDetail" sh bin/catalina.sh start複製程式碼
使用 Java Flight Recorder 分析 Java 應用效能
JFR(Java Flight Recorder)是 JVM 內建的基於事件的效能分析特性,這是 Oracle JDK7u4 版本開始提供的商業特性,2018 年的時候在 JDK11 上開源了這個特性,但是一直沒有針對 JDK8 版本的支援。
阿里巴巴和 RedHat、Azul、Amazon 等公司一起合作嘗試把這個特性移植回 JDK8上,不過該 patch 暫時還沒有合併回 OpenJDK8u倉庫,我們在 Alibaba Dragonwell 8 中提供了 Alibaba 移植的 JFR 版本,用於幫助使用者提前獲取這方面的支援。
JFR 的用法很簡單,使用者使用命令列引數或者 jcmd 命令控制 HotSpot 輸出效能資料到檔案中,然後就能使用開源的 jmc 工具在圖形介面中開啟、分析生成的資料檔案了。
使用 JFR 收集效能資料
在 Alibaba Dragonwell 8中,預設情況下 JFR 特性是處於關閉的狀態,必須新增命令列引數 -XX:+EnableJFR
來允許使用 JFR 特性。 Alibaba Dragonwell 8 提供了不同的方式來使用 JFR 採集效能資料。
應用可以可以通過命令列引數指定 JFR 再啟動後立馬開始採集資料,這個對於診斷啟動階段的問題會很有幫助。下面的示例命令會在 Java 程式的 JFR 模組初始化後就開始收集 JFR 資料,持續一分鐘,並且把資料都輸出到名為rec.jfr 的檔案中。
JAVA_HOME=/path/to/dragonwell8/installation JAVA_OPTS="-XX:+EnableJFR -XX:StartFlightRecording=duration=1m,filename=rec.jfr" sh bin/catalina.sh start複製程式碼
應用也可以只新增 -XX:+EnableJFR
,然後通過 jcmd
命令在應用啟動後的任意時間點開始採集資料,這種情況更加靈活可控,可以滿足隨時隨地進行分析的需求。
以 Tomcat 為例,啟動 Tomcat 的命令可以是:
JAVA_HOME=/path/to/dragonwell8/installation JAVA_OPTS="-XX:+EnableJFR" sh bin/catalina.sh start複製程式碼
當需要收集資料進行分析時,只需要使用目標 Tomcat 程式的 PID 來執行 JFR 對應的 jcmd 命令即可。以 Tomcat 為例,如果需要在指定時刻開始收集 10 秒的資料,那麼觸發的命令如下:
$ ps ax | grep tomcat
77522 pts/18 Sl+ 0:08 /home/chuansheng.lcs/dw_test/apache-tomcat-8.5.39/../j2sdk-image/bin/java -Djava.util.logging.config.file=/home/chuansheng.lcs/dw_test/apache-tomcat-8.5.39/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -XX:+EnableJFR -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /home/chuansheng.lcs/dw_test/apache-tomcat-8.5.39/bin/bootstrap.jar:/home/chuansheng.lcs/dw_test/apache-tomcat-8.5.39/bin/tomcat-juli.jar -Dcatalina.base=/home/chuansheng.lcs/dw_test/apache-tomcat-8.5.39 -Dcatalina.home=/home/chuansheng.lcs/dw_test/apache-tomcat-8.5.39 -Djava.io.tmpdir=/home/chuansheng.lcs/dw_test/apache-tomcat-8.5.39/temp org.apache.catalina.startup.Bootstrap start
98451 pts/22 S+ 0:00 grep --color=auto tomcat
$ dragonwell8_home/bin/jcmd 77522 JFR.start duration=10s filename=$PWD/rec3.jfr
77522:
Started recording 3. The result will be written to:
/home/my/workdir/rec3.jfr複製程式碼
10 秒之後可以看到生成了 JFR 資料檔案/home/my/workdir/rec3.jfr,使用 JMC 即可進行分析。
也可以不指定收集資料的時間,直接啟動 JFR 收集,並且在需要的時候手動把所有生成的資料一次性 dump 到檔案,
$ dragonwell8_home/bin/jcmd 2823 JFR.start filename=$PWD/rec4.jfr
2823:
Started recording 4. No limit specified, using maxsize=250MB as default.
Use JFR.dump name=4 to copy recording data to file.
$ dragonwell8_home/bin/jcmd 2823 JFR.dump name=4 filename=rec4.jfr
2823:
Dumped recording "Recording-4", 332.7 kB written to:
/path/to/my/workdir/rec4.jfr複製程式碼
使用 JMC 分析效能
JFR 記錄 Java 應用效能資料的輸出是一個二進位制的檔案,我們藉助於 JMC(Java Mission Control) 工具可以在圖形化介面裡面分析具體的效能資料。這個工具是開源產品,沒有包括在 Alibaba Dragonwell 8裡面,需要到 OpenJDK 的官方網站下載使用,jdk.java.net/jmc/。
請注意, Alibaba Dragonwell8 生成的JFR資料檔案需要 7.0 或更高版本的 JMC 工具來分析。
開啟 JMC 後,可以點選左側的詳細類別來詳細分析取樣時間段內發生的各種事件。
診斷除錯支援
Alibaba Dragonwell 8 還內建一些方便的診斷特性,主要包括
大物件分配報警
可以通過新的 JVM 引數"-XX:ArrayAllocationWarningSize=",比如下面程式碼中分配了比較大的陣列
public static void main(String[] args) {
doAlloc(32 * 1024 * 1024 + 1);
}
private static Object doAlloc(int size) {
return new byte[size];
}複製程式碼
執行時如果新增 ArrayAllocationWarningSize 選項就會列印出分配該陣列時的 Java 堆疊
詳細的 ParNew GC 日誌支援
Alibaba Dragonwell 8 預設使用了 CMS (Concurrent Mark Sweep) 演算法,新生代使用了 ParNew 演算法,所以內建兩個針對 ParNew GC 日誌的增強
- 可以通過 jinfo 工具設定 PrintYoungGenHistoAfterParNewGC 選項來在下一次 Young GC 結束的時候列印新生代的物件型別直方圖。命令如下
jinfo -flag +PrintYoungGenHistoAfterParNewGC <pid>複製程式碼
列印完成後,這個選項會被重置回 false 狀態,防止過多的輸出,一個典型的輸出例子如下:
- 可以通過-XX:+PrintGCRootsTraceTime 來列印處理每一類 GC 根集所花費的詳細 CPU 時間,輸出示例如下:
精簡版 HeapDump 支援
Alibaba Dragonwell 8 的 jmap 工具支援一個新的 dump 選項“mini”可以在做 heapdump 的時候跳過所有的原始型別陣列的內容,從而大大減小生成的 heapdump 檔案大小,這對於只需要排查型別、物件關係的場景會比較有幫助。
示例命令如下:
本文為雲棲社群原創內容,未經允許不得轉載。