JVM崩溃时GC日志被覆盖

6
我正在为 G1GC 调整我们的产品,作为测试的一部分,我在我的 Spark Workers 上经常遇到段错误问题,这当然导致 JVM 崩溃。当发生这种情况时,Spark Worker/Executor JVM 会自动重新启动,这将覆盖之前 Executor JVM 写入的 GC 日志。
老实说,我不太确定 Executor JVM 如何重启自身的机制,但我通过 init.d 启动了 Spark Driver 服务,该服务又调用一个 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"

我认为问题在于此脚本将这些选项发送到Spark Driver,然后通过-Dspark.executor.extraJavaOptions参数将它们传递给Spark Executors(通过不同的服务器),当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 &

这使得我难以调试导致 JVM 崩溃的原因,因为我失去了导致崩溃的 Workers 的活动和状态。你有什么好的办法来处理这种情况,并在 JVM 崩溃/segfault 后保留 Workers 的 GC 日志吗?

1个回答

2

如果您正在使用Java 8及以上版本,可以考虑在日志文件名中添加%p以引入PID,这将在每次崩溃时生成一种唯一的标识。


这会遇到与我在GC日志名称中输入的日期相同的问题:一旦到达执行器,它基本上是静态的。 - liltitus27

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接