Uber JVM Profiler จัดเตรียม Java Agent เพื่อรวบรวมตัววัดและสแต็กเทรซต่างๆ สำหรับกระบวนการ Hadoop/Spark JVM ในลักษณะแบบกระจาย เช่น ตัววัด CPU/หน่วยความจำ/IO
นอกจากนี้ Uber JVM Profiler ยังมีความสามารถในการสร้างโปรไฟล์ขั้นสูงเพื่อติดตามวิธีการและอาร์กิวเมนต์ Java ที่กำหนดเองบนโค้ดผู้ใช้ โดยไม่ต้องเปลี่ยนโค้ดผู้ใช้ คุณลักษณะนี้สามารถใช้เพื่อติดตามเวลาแฝงการเรียกโหนดชื่อ HDFS สำหรับแต่ละแอปพลิเคชัน Spark และระบุคอขวดของโหนดชื่อ นอกจากนี้ยังสามารถติดตามเส้นทางไฟล์ HDFS ที่แต่ละแอปพลิเคชัน Spark อ่านหรือเขียน และระบุไฟล์ยอดนิยมเพื่อการปรับให้เหมาะสมยิ่งขึ้น
ตัวสร้างโปรไฟล์นี้ถูกสร้างขึ้นตั้งแต่แรกเพื่อจัดทำโปรไฟล์แอปพลิเคชัน Spark ซึ่งโดยปกติจะมีกระบวนการ/เครื่องจักรหลายสิบหรือหลายร้อยรายการสำหรับแอปพลิเคชันเดียว ดังนั้นผู้คนจึงสามารถเชื่อมโยงหน่วยวัดของกระบวนการ/เครื่องจักรที่แตกต่างกันเหล่านี้ได้อย่างง่ายดาย นอกจากนี้ยังเป็น Java Agent ทั่วไปและสามารถใช้สำหรับกระบวนการ JVM ใดๆ ได้เช่นกัน
mvn clean package
คำสั่งนี้สร้างไฟล์ jvm-profiler.jar โดยมี Reporter ดีฟอลต์ เช่น ConsoleOutputReporter, FileOutputReporter และ KafkaOutputReporter รวมอยู่ด้วย หากคุณต้องการรวมกลุ่มผู้รายงานที่กำหนดเอง เช่น RedisOutputReporter หรือ InfluxDBOutputReporter ในไฟล์ jar ให้ระบุ id โปรไฟล์ maven สำหรับผู้รายงานนั้นในคำสั่ง build ตัวอย่างเช่น หากต้องการสร้างไฟล์ jar ด้วย RedisOutputReporter คุณสามารถดำเนินการคำสั่ง mvn -P redis clean package
ได้ โปรดตรวจสอบไฟล์ pom.xml เพื่อดูผู้รายงานที่กำหนดเองและรหัสโปรไฟล์ของพวกเขา
คุณสามารถอัปโหลดไฟล์ jar jvm-profiler ไปยัง 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
ใช้คำสั่งต่อไปนี้เพื่อรัน jvmprofiler ด้วยแอปพลิเคชัน jar ที่เรียกใช้งานได้
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
ตั้งค่า jvmprofiler ใน CATALINA_OPTS ก่อนเริ่มต้นเซิร์ฟเวอร์ Tomcat ตรวจสอบไฟล์ 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"
ใช้คำสั่งต่อไปนี้เพื่อใช้ jvmprofiler กับ 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 Profiler
Uber JVM Profiler รองรับคุณสมบัติดังต่อไปนี้:
แก้ไขข้อบกพร่องการใช้หน่วยความจำสำหรับผู้เรียกใช้แอปพลิเคชัน Spark ทั้งหมดของคุณ รวมถึงหน่วยความจำฮีป java, หน่วยความจำที่ไม่ใช่ฮีป, หน่วยความจำดั้งเดิม (VmRSS, VmHWM), พูลหน่วยความจำ และพูลบัฟเฟอร์ (บัฟเฟอร์แบบกำหนดทิศทาง/แมป)
ดีบักการใช้งาน CPU, เวลาการรวบรวมขยะสำหรับผู้ดำเนินการ Spark ทั้งหมด
ดีบักเมธอดคลาส Java ที่กำหนดเอง (เรียกใช้กี่ครั้ง ใช้ระยะเวลาเท่าใด) เราเรียกมันว่าการสร้างโปรไฟล์ระยะเวลา
ดีบักการเรียกเมธอดคลาส Java โดยพลการและติดตามค่าอาร์กิวเมนต์ เราเรียกมันว่าการทำโปรไฟล์อาร์กิวเมนต์
ทำ Stacktrack Profiling และสร้าง Flamegraph เพื่อแสดงภาพเวลา CPU ที่ใช้สำหรับแอปพลิเคชัน Spark
ดีบักตัววัด IO (ไบต์การอ่าน/เขียนดิสก์สำหรับแอปพลิเคชัน, CPU iowait สำหรับเครื่อง)
ดีบักตัววัดเธรด JVM เช่น จำนวนเธรดทั้งหมด เธรดสูงสุด เธรดที่ใช้งานอยู่ และเธรดใหม่
java agent สนับสนุนพารามิเตอร์ต่อไปนี้ ซึ่งสามารถใช้ในบรรทัดรับคำสั่ง Java เช่น "-javaagent:agent_jar_file.jar=param1=value1,param2=value2":
Reporter: ชื่อคลาสของผู้รายงาน เช่น com.uber.profiling.reporters.ConsoleOutputReporter หรือ com.uber.profiling.reporters.KafkaOutputReporter ซึ่งมีการใช้งานอยู่แล้วในโค้ด คุณสามารถใช้นักข่าวของคุณเองและตั้งชื่อได้ที่นี่
configProvider: ชื่อคลาสสำหรับผู้ให้บริการกำหนดค่า เช่น com.uber.profiling.YamlConfigProvider ซึ่งมีการใช้งานในโค้ดแล้ว คุณสามารถใช้ผู้ให้บริการกำหนดค่าของคุณเองและตั้งชื่อได้ที่นี่
configFile: เส้นทางไฟล์กำหนดค่าที่จะใช้โดย YamlConfigProvider (หากตั้งค่า configProvider เป็น com.uber.profiling.YamlConfigProvider) นี่อาจเป็นเส้นทางของไฟล์ในเครื่องหรือ URL HTTP
แท็ก: สตริงข้อความธรรมดาซึ่งจะถูกรายงานพร้อมกับเมตริก
metricInterval: ความถี่ในการรวบรวมและรายงานตัววัด หน่วยเป็นมิลลิวินาที
DurationProfiling: กำหนดค่าโปรไฟล์คลาสและวิธีการเฉพาะ เช่น com.uber.profiling.examples.HelloWorldApplication.publicSleepMethod นอกจากนี้ยังรองรับไวด์การ์ด (*) สำหรับชื่อเมธอด เช่น com.uber.profiling.examples.HelloWorldApplication.*
argumentProfiling: กำหนดค่าให้กับโปรไฟล์อาร์กิวเมนต์เมธอดเฉพาะ เช่น com.uber.profiling.examples.HelloWorldApplication.publicSleepMethod.1 (".1" หมายถึงการรับค่าสำหรับอาร์กิวเมนต์แรกและส่งออกไปในตัวรายงาน)
SampleInterval: ความถี่ (มิลลิวินาที) ในการทำ Stacktrace Sampling หากไม่ได้ตั้งค่านี้หรือเป็นศูนย์ Profiler จะไม่ทำการสุ่มตัวอย่าง Stacktrace
ioProfiling: ไม่ว่าจะทำโปรไฟล์ตัวชี้วัด IO อาจเป็นจริงหรือเท็จก็ได้
BrokerList: รายชื่อนายหน้าหากใช้ com.uber.profiling.reporters.KafkaOutputReporter
topicPrefix: คำนำหน้าหัวข้อหากใช้ com.uber.profiling.reporters.KafkaOutputReporter KafkaOutputReporter จะส่งการวัดไปยังหลายหัวข้อโดยมีค่านี้เป็นคำนำหน้าสำหรับชื่อหัวข้อ
outputDir: ไดเร็กทอรีเอาต์พุตหากใช้ com.uber.profiling.reporters.FileOutputReporter FileOutputReporter จะเขียนเมตริกลงในไดเร็กทอรีนี้
พารามิเตอร์สามารถระบุเป็นอาร์กิวเมนต์ในคำสั่ง java หรือในไฟล์กำหนดค่า YAML หากคุณใช้ configProvider=com.uber.profiling.YamlConfigProvider ต่อไปนี้เป็นตัวอย่างของไฟล์กำหนดค่า YAML:
reporter: com.uber.profiling.reporters.ConsoleOutputReporter
metricInterval: 5000
ต่อไปนี้เป็นตัวอย่างของตัววัด CPU และหน่วยความจำเมื่อใช้ ConsoleOutputReporter หรือ KafkaOutputReporter:
{
"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
คำสั่งต่อไปนี้จะยุบไฟล์เอาต์พุต json ของ Stacktrack Profiling ไปเป็นรูปแบบไฟล์อินพุตสำหรับสร้างกราฟฟลากราฟ สามารถดูสคริปต์ flamegraph.pl
ได้ที่ FlameGraph
python stackcollapse.py -i Stacktrace.json > Stacktrace.folded
flamegraph.pl Stacktrace.folded > Stacktrace.svg
โปรดทราบว่าจำเป็นต้องเปิดใช้งานการสุ่มตัวอย่างแบบสแต็กเทรซเพื่อสร้างกราฟฟลากราฟ หากต้องการเปิดใช้งาน โปรดตั้งค่าพารามิเตอร์ sampleInterval
หากไม่ได้ตั้งค่าหรือเป็นศูนย์ ตัวสร้างโปรไฟล์จะไม่ทำการสุ่มตัวอย่างสแต็กเทรซ