Uber JVM 프로파일러는 Hadoop/Spark JVM 프로세스에 대한 다양한 지표와 스택 추적을 분산 방식으로 수집하는 Java 에이전트를 제공합니다(예: CPU/메모리/IO 지표).
Uber JVM 프로파일러는 사용자 코드 변경 요구 사항 없이 사용자 코드에서 임의의 Java 메서드와 인수를 추적할 수 있는 고급 프로파일링 기능도 제공합니다. 이 기능은 각 Spark 애플리케이션에 대한 HDFS 네임 노드 호출 대기 시간을 추적하고 네임 노드의 병목 현상을 식별하는 데 사용할 수 있습니다. 또한 각 Spark 애플리케이션이 읽거나 쓰는 HDFS 파일 경로를 추적하고 추가 최적화를 위해 핫 파일을 식별할 수 있습니다.
이 프로파일러는 처음에 단일 애플리케이션에 대해 일반적으로 수십 또는 수백 개의 프로세스/머신이 있는 Spark 애플리케이션을 프로파일링하기 위해 생성되었으므로 사람들은 이러한 다양한 프로세스/머신의 메트릭을 쉽게 상호 연관시킬 수 있습니다. 또한 일반 Java 에이전트이며 모든 JVM 프로세스에도 사용할 수 있습니다.
mvn clean package
이 명령은 ConsoleOutputReporter, FileOutputReporter 및 KafkaOutputReporter와 같은 기본 리포터가 번들로 포함된 jvm-profiler.jar 파일을 생성합니다. RedisOutputReporter 또는 InfluxDBOutputReporter와 같은 사용자 정의 보고자를 jar 파일에 묶으려면 빌드 명령에서 해당 보고자에 대한 maven 프로필 ID를 제공하세요. 예를 들어 RedisOutputReporter를 사용하여 jar 파일을 빌드하려면 mvn -P redis clean package
명령을 실행할 수 있습니다. 사용 가능한 사용자 정의 보고자와 해당 프로필 ID는 pom.xml 파일을 확인하세요.
Spark 애플리케이션 실행자가 액세스할 수 있도록 jvm-profiler jar 파일을 HDFS에 업로드할 수 있습니다. 그런 다음 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 프로파일러를 실행하려면 다음 명령을 사용하십시오.
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 프로파일러를 설정하십시오. 메트릭은 로그/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"
Spring Boot 2.x에서 jvm 프로파일러를 사용하려면 다음 명령을 사용하십시오. Spring Boot 1.x의 경우 다음 명령에서 -Dspring-boot.run.jvmArguments
대신 -Drun.arguments
사용하십시오.
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 프로파일러는 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 프로파일러는 다음 기능을 지원합니다.
Java 힙 메모리, 비힙 메모리, 기본 메모리(VmRSS, VmHWM), 메모리 풀, 버퍼 풀(지정/매핑 버퍼)을 포함한 모든 Spark 애플리케이션 실행기의 메모리 사용량을 디버그합니다.
모든 스파크 실행기에 대한 CPU 사용량, 가비지 수집 시간을 디버그합니다.
임의의 Java 클래스 메소드를 디버그합니다(실행 횟수, 소요 시간). 우리는 이를 기간 프로파일링이라고 부릅니다.
임의의 Java 클래스 메소드 호출을 디버그하고 인수 값을 추적합니다. 우리는 이를 인수 프로파일링이라고 부릅니다.
Stacktrack Profiling을 수행하고 Flamegraph를 생성하여 Spark 애플리케이션에 소요된 CPU 시간을 시각화합니다.
IO 측정항목(애플리케이션의 디스크 읽기/쓰기 바이트, 머신의 CPU iowait)을 디버그합니다.
총 스레드 수, 최대 스레드, 라이브/활성 스레드 및 신규 스레드와 같은 JVM 스레드 지표를 디버깅합니다.
Java 에이전트는 "-javaagent:agent_jar_file.jar=param1=value1,param2=value2"와 같이 Java 명령줄에서 사용할 수 있는 다음 매개 변수를 지원합니다.
reporter: 리포터의 클래스 이름(예: com.uber.profiling.reporters.ConsoleOutputReporter 또는 com.uber.profiling.reporters.KafkaOutputReporter)은 이미 코드에 구현되어 있습니다. 자신만의 리포터를 구현하고 여기에서 이름을 설정할 수 있습니다.
configProvider: 구성 공급자의 클래스 이름입니다(예: 코드에 이미 구현되어 있는 com.uber.profiling.YamlConfigProvider). 자신만의 구성 공급자를 구현하고 여기에서 이름을 설정할 수 있습니다.
configFile: YamlConfigProvider에서 사용할 구성 파일 경로입니다(configProvider가 com.uber.profiling.YamlConfigProvider로 설정된 경우). 이는 로컬 파일 경로 또는 HTTP URL일 수 있습니다.
태그: 측정항목과 함께 보고될 일반 텍스트 문자열입니다.
metricInterval: 지표를 수집하고 보고하는 빈도(밀리초)입니다.
DurationProfiling: 특정 클래스 및 메소드를 프로파일링하도록 구성합니다(예: com.uber.profiling.examples.HelloWorldApplication.publicSleepMethod). 또한 메소드 이름에 와일드카드(*)를 지원합니다(예: com.uber.profiling.examples.HelloWorldApplication.*).
ArgumentProfiling: 특정 메서드 인수를 프로파일링하도록 구성합니다(예: com.uber.profiling.examples.HelloWorldApplication.publicSleepMethod.1(".1"은 첫 번째 인수에 대한 값을 가져와 보고자에서 보내는 것을 의미함).
SampleInterval: 스택 추적 샘플링을 수행하는 빈도(밀리초). 이 값이 설정되지 않거나 0인 경우 프로파일러는 스택 추적 샘플링을 수행하지 않습니다.
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의 출력을 사용하여 Flamegraph를 생성하여 CPU 시간을 시각화할 수 있습니다. Python 스크립트 stackcollapse.py
를 사용하여 다음 명령은 Stacktrack Profiling json 출력 파일을 Flamegraph 생성을 위한 입력 파일 형식으로 축소합니다. flamegraph.pl
스크립트는 FlameGraph에서 찾을 수 있습니다.
python stackcollapse.py -i Stacktrace.json > Stacktrace.folded
flamegraph.pl Stacktrace.folded > Stacktrace.svg
Flamegraph를 생성하려면 스택 추적 샘플링을 활성화해야 합니다. 활성화하려면 sampleInterval
매개변수를 설정하세요. 설정되지 않거나 0이면 프로파일러는 스택 추적 샘플링을 수행하지 않습니다.