我正在為G1GC調整我們的産品,作為測試的一部分,我在Spark Workers上遇到了正常的段錯誤,這當然會導緻JVM崩潰.發生這種情況時,Spark Worker / Executor JVM會自動重新啟動,然後會覆寫為以前的Executor JVM編寫的GC日志.
說實話,我不太确定Executor JVM如何重新開機自己的機制,但是我通過init.d啟動了Spark Driver服務,而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"
我認為問題是這個腳本将這些選項發送到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 &
這使我很難調試段錯誤的原因,因為我正在失去導緻JVM崩潰的Workers的活動和狀态.有關如何處理這種情況并将GC日志保留在Workers上的任何想法,即使在JVM崩潰/段錯誤之後?