JVM崩溃时GC日志被覆盖

lil*_*s27 6 java garbage-collection g1gc apache-spark

我正在为G1GC调整我们的产品,作为测试的一部分,我在Spark Workers上遇到了常规的段错误,这当然会导致JVM崩溃.发生这种情况时,Spark Worker/Executor JVM会自动重新启动,然后会覆盖为以前的Executor JVM编写的GC日志.

说实话,我不太确定Executor JVM如何重启自己的机制,但是我启动了Spark驱动程序服务init.d,然后调用bash脚本.我在该脚本中使用了一个时间戳,该时间戳附加到GC日志文件名:

today=$(date +%Y%m%dT%H%M%S%3N)

SPARK_HEAP_DUMP="-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${SPARK_LOG_HOME}/heapdump_$$_${today}.hprof"
SPARK_GC_LOGS="-Xloggc:${SPARK_LOG_HOME}/gc_${today}.log -XX:LogFile=${SPARK_LOG_HOME}/safepoint_${today}.log"

GC_OPTS="-XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:+PrintFlagsFinal -XX:+PrintJNIGCStalls -XX:+PrintTLAB -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=15 -XX:GCLogFileSize=48M -XX:+PrintTenuringDistribution -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime -XX:+PrintAdaptiveSizePolicy -XX:+PrintHeapAtGC -XX:+PrintGCCause -XX:+PrintReferenceGC -XX:+PrintSafepointStatistics -XX:PrintSafepointStatisticsCount=1"
Run Code Online (Sandbox Code Playgroud)

认为问题是这个脚本将这些选项发送到Spark驱动程序,然后Spark驱动程序将它们传递给Spark Executors(通过-Dspark.executor.extraJavaOptions参数),它们都是独立的服务器,当Executor JVM崩溃时,它只是使用命令最初被发送以开始备份,这意味着GC日志文件名的时间戳部分是静态的:

SPARK_STANDALONE_OPTS=`property ${SPARK_APP_CONFIG}/spark.properties "spark-standalone.extra.args"`
SPARK_STANDALONE_OPTS="$SPARK_STANDALONE_OPTS $GC_OPTS $SPARK_GC_LOGS $SPARK_HEAP_DUMP"

exec java ${SPARK_APP_HEAP_DUMP} ${GC_OPTS} ${SPARK_APP_GC_LOGS} \
    ${DRIVER_JAVA_OPTIONS} \
    -Dspark.executor.memory=${EXECUTOR_MEMORY} \
    -Dspark.executor.extraJavaOptions="${SPARK_STANDALONE_OPTS}" \
    -classpath ${CLASSPATH} \
    com.company.spark.Main >> ${SPARK_APP_LOGDIR}/${SPARK_APP_LOGFILE} 2>&1 &
Run Code Online (Sandbox Code Playgroud)

这使我很难调试段错误的原因,因为我正在失去导致JVM崩溃的Workers的活动和状态.有关如何处理这种情况并将GC日志保留在Workers上的任何想法,即使在JVM崩溃/段错误之后?

小智 2

如果您使用的是 Java 8 及更高版本,您可以考虑通过在日志文件名中添加 %p 来引入 PID,每次崩溃时该 PID 都是唯一的。