Uber JVM Profiler 提供了一個 Java Agent,以分散式方式收集 Hadoop/Spark JVM 進程的各種指標和堆疊跟踪,例如 CPU/記憶體/IO 指標。
Uber JVM Profiler 還提供進階分析功能,可追蹤使用者程式碼上的任意 Java 方法和參數,而無需更改使用者程式碼。此功能可用於追蹤每個 Spark 應用程式的 HDFS 名稱節點呼叫延遲並識別名稱節點的瓶頸。它還可以追蹤每個 Spark 應用程式讀取或寫入的 HDFS 檔案路徑,並識別熱點檔案以進行進一步最佳化。
該分析器最初是為了分析 Spark 應用程式而創建的,這些應用程式通常在單一應用程式中具有數十或數百個進程/機器,因此人們可以輕鬆地將這些不同進程/機器的指標關聯起來。它也是一個通用的 Java 代理,也可用於任何 JVM 進程。
mvn clean package
此命令建立jvm-profiler.jar文件,其中捆綁了預設報告器(例如 ConsoleOutputReporter、FileOutputReporter 和 KafkaOutputReporter)。如果您想要將自訂報告器(如 RedisOutputReporter 或 InfluxDBOutputReporter)捆綁到 jar 檔案中,請在建置命令中提供該報告器的 Maven 設定檔 ID。例如,要使用 RedisOutputReporter 建構 jar 文件,可以執行mvn -P redis clean package
指令。請檢查 pom.xml 檔案以取得可用的自訂記者及其個人資料 ID。
您可以將 jvm-profiler jar 檔案上傳到 HDFS,以便 Spark 應用程式執行器可以存取它。然後在啟動 Spark 應用程式時添加如下配置:
--conf spark.jars=hdfs://hdfs_url/lib/jvm-profiler-1.0.0.jar
--conf spark.executor.extraJavaOptions=-javaagent:jvm-profiler-1.0.0.jar
以下命令將啟動附加了探查器代理的範例應用程序,該代理將向控制台輸出報告指標:
java -javaagent:target/jvm-profiler-1.0.0.jar=reporter=com.uber.profiling.reporters.ConsoleOutputReporter,tag=mytag,metricInterval=5000,durationProfiling=com.uber.profiling.examples.HelloWorldApplication.publicSleepMethod,argumentProfiling=com.uber.profiling.examples.HelloWorldApplication.publicSleepMethod.1,sampleInterval=100 -cp target/jvm-profiler-1.0.0.jar com.uber.profiling.examples.HelloWorldApplication
使用以下命令運行帶有可執行 jar 應用程式的 jvm profiler。
java -javaagent:/opt/jvm-profiler/target/jvm-profiler-1.0.0.jar=reporter=com.uber.profiling.reporters.ConsoleOutputReporter,metricInterval=5000,durationProfiling=foo.bar.FooAppication.barMethod,sampleInterval=5000 -jar foo-application.jar
在啟動 tomcat 伺服器之前,在 CATALINA_OPTS 中設定 jvm profiler。檢查logs/catalina.out 檔案中的指標。
export CATALINA_OPTS="$CATALINA_OPTS -javaagent:/opt/jvm-profiler/target/jvm-profiler-1.0.0.jar=reporter=com.uber.profiling.reporters.ConsoleOutputReporter,metricInterval=5000,durationProfiling=foo.bar.FooController.barMethod,sampleInterval=5000"
使用以下命令將 jvm profiler 與 Spring Boot 2.x 結合使用。對於 Spring Boot 1.x,在以下命令中使用-Drun.arguments
而不是-Dspring-boot.run.jvmArguments
。
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-javaagent:/opt/jvm-profiler/target/jvm-profiler-1.0.0.jar=reporter=com.uber.profiling.reporters.ConsoleOutputReporter,metricInterval=5000,durationProfiling=foo.bar.FooController.barMethod,sampleInterval=5000"
Uber JVM Profiler 支援將指標傳送到 Kafka。例如,
java -javaagent:target/jvm-profiler-1.0.0.jar=reporter=com.uber.profiling.reporters.KafkaOutputReporter,metricInterval=5000,brokerList=localhost:9092,topicPrefix=profiler_ -cp target/jvm-profiler-1.0.0.jar com.uber.profiling.examples.HelloWorldApplication
它將向 Kafka 主題 profiler_CpuAndMemory 發送指標。有關指標的範例,請參閱本文檔底部。
請參閱 JVM 探查器部落格文章。
Uber JVM Profiler 支援以下功能:
除錯所有 Spark 應用程式執行器的記憶體使用情況,包括 java 堆記憶體、非堆記憶體、本機記憶體(VmRSS、VmHWM)、記憶體池和緩衝池(定向/映射緩衝區)。
調試所有 Spark 執行器的 CPU 使用情況、垃圾收集時間。
偵錯任意 java 類別方法(它們運行了多少次,它們花費了多少時間)。我們稱之為持續時間分析。
偵錯任意 java 類別方法呼叫並追蹤它的參數值。我們稱之為參數分析。
進行 Stacktrack 分析並產生火焰圖,以視覺化 Spark 應用程式所花費的 CPU 時間。
調試 IO 指標(應用程式的磁碟讀/寫字節,機器的 CPU iowait)。
調試 JVM 線程指標,例如總線程數、峰值線程、活動/活動線程和新線程。
java代理程式支援以下參數,可以在Java命令列中使用,例如「-javaagent:agent_jar_file.jar=param1=value1,param2=value2」:
reports:報告器的類別名,例如 com.uber.profiling.reporters.ConsoleOutputReporter 或 com.uber.profiling.reporters.KafkaOutputReporter,這些已在程式碼中實作。您可以實現自己的記者並在此處設定名稱。
configProvider:設定提供者的類別名,例如 com.uber.profiling.YamlConfigProvider,已在程式碼中實作。您可以實現自己的配置提供者並在此處設定名稱。
configFile:YamlConfigProvider 所使用的設定檔路徑(如果 configProvider 設定為 com.uber.profiling.YamlConfigProvider)。這可以是本機檔案路徑或 HTTP URL。
tag:純文字字串,將與指標一起報告。
metricInterval:收集和報告指標的頻率(以毫秒為單位)。
urationProfiling:設定以分析特定的類別和方法,例如com.uber.profiling.examples.HelloWorldApplication.publicSleepMethod。它也支援方法名稱的通配符(*),例如com.uber.profiling.examples.HelloWorldApplication.*。
argumentProfiling:設定為分析特定方法參數,例如 com.uber.profiling.examples.HelloWorldApplication.publicSleepMethod.1(「.1」表示取得第一個參數的值並在報告器中傳送)。
SampleInterval:進行堆疊追蹤取樣的頻率(毫秒),如果該值未設定或為零,則探查器將不會進行堆疊追蹤取樣。
ioProfiling:是否分析 IO 指標,可以是 true 或 false。
BrokerList:如果使用 com.uber.profiling.reporters.KafkaOutputReporter,則為代理程式清單。
topicPrefix:如果使用 com.uber.profiling.reporters.KafkaOutputReporter,則為主題前綴。 KafkaOutputReporter 會將指標傳送到多個主題,並以此值作為主題名稱的前綴。
outputDir:如果使用 com.uber.profiling.reporters.FileOutputReporter,則為輸出目錄。 FileOutputReporter 會將指標寫入此目錄。
這些參數可以作為 java 命令中的參數提供,如果您使用 configProvider=com.uber.profiling.YamlConfigProvider,也可以在 YAML 設定檔中提供。以下是 YAML 設定檔的範例:
reporter: com.uber.profiling.reporters.ConsoleOutputReporter
metricInterval: 5000
以下是使用 ConsoleOutputReporter 或 KafkaOutputReporter 時的 CPU 和記憶體指標範例:
{
"nonHeapMemoryTotalUsed" : 11890584.0 ,
"bufferPools" : [
{
"totalCapacity" : 0 ,
"name" : " direct " ,
"count" : 0 ,
"memoryUsed" : 0
},
{
"totalCapacity" : 0 ,
"name" : " mapped " ,
"count" : 0 ,
"memoryUsed" : 0
}
],
"heapMemoryTotalUsed" : 24330736.0 ,
"epochMillis" : 1515627003374 ,
"nonHeapMemoryCommitted" : 13565952.0 ,
"heapMemoryCommitted" : 257425408.0 ,
"memoryPools" : [
{
"peakUsageMax" : 251658240 ,
"usageMax" : 251658240 ,
"peakUsageUsed" : 1194496 ,
"name" : " Code Cache " ,
"peakUsageCommitted" : 2555904 ,
"usageUsed" : 1173504 ,
"type" : " Non-heap memory " ,
"usageCommitted" : 2555904
},
{
"peakUsageMax" : -1 ,
"usageMax" : -1 ,
"peakUsageUsed" : 9622920 ,
"name" : " Metaspace " ,
"peakUsageCommitted" : 9830400 ,
"usageUsed" : 9622920 ,
"type" : " Non-heap memory " ,
"usageCommitted" : 9830400
},
{
"peakUsageMax" : 1073741824 ,
"usageMax" : 1073741824 ,
"peakUsageUsed" : 1094160 ,
"name" : " Compressed Class Space " ,
"peakUsageCommitted" : 1179648 ,
"usageUsed" : 1094160 ,
"type" : " Non-heap memory " ,
"usageCommitted" : 1179648
},
{
"peakUsageMax" : 1409286144 ,
"usageMax" : 1409286144 ,
"peakUsageUsed" : 24330736 ,
"name" : " PS Eden Space " ,
"peakUsageCommitted" : 67108864 ,
"usageUsed" : 24330736 ,
"type" : " Heap memory " ,
"usageCommitted" : 67108864
},
{
"peakUsageMax" : 11010048 ,
"usageMax" : 11010048 ,
"peakUsageUsed" : 0 ,
"name" : " PS Survivor Space " ,
"peakUsageCommitted" : 11010048 ,
"usageUsed" : 0 ,
"type" : " Heap memory " ,
"usageCommitted" : 11010048
},
{
"peakUsageMax" : 2863661056 ,
"usageMax" : 2863661056 ,
"peakUsageUsed" : 0 ,
"name" : " PS Old Gen " ,
"peakUsageCommitted" : 179306496 ,
"usageUsed" : 0 ,
"type" : " Heap memory " ,
"usageCommitted" : 179306496
}
],
"processCpuLoad" : 0.0008024004394748531 ,
"systemCpuLoad" : 0.23138430784607697 ,
"processCpuTime" : 496918000 ,
"appId" : null ,
"name" : " 24103@machine01 " ,
"host" : " machine01 " ,
"processUuid" : " 3c2ec835-749d-45ea-a7ec-e4b9fe17c23a " ,
"tag" : " mytag " ,
"gc" : [
{
"collectionTime" : 0 ,
"name" : " PS Scavenge " ,
"collectionCount" : 0
},
{
"collectionTime" : 0 ,
"name" : " PS MarkSweep " ,
"collectionCount" : 0
}
]
}
您可以在此處找到所有指標及其對應資訊的清單。
我們可以利用 Stacktrack Profiling 的輸出來產生火焰圖來視覺化 CPU 時間。使用 Python 腳本stackcollapse.py
,以下命令會將 Stacktrack Profiling json 輸出檔案折疊為用於產生火焰圖的輸入檔案格式。腳本flamegraph.pl
可以在 FlameGraph 找到。
python stackcollapse.py -i Stacktrace.json > Stacktrace.folded
flamegraph.pl Stacktrace.folded > Stacktrace.svg
請注意,需要啟用堆疊追蹤採樣才能產生火焰圖。若要啟用它,請設定sampleInterval
參數。如果未設定或為零,探查器將不會進行堆疊追蹤採樣。