此文已由作者岳猛授權網易雲社區發布。
歡迎訪問網易雲社區,了解更多網易技術產品運營經驗。
任何時候日志都是定位問題的關鍵,spark也不會例外,合適的配置和獲取spark的driver,am,及executor日志將會提升問題定位的效率,這里初步整理了spark的一些配置,更好的日志配置還需要根據實際的情況。
1)dirver日志的配置,可以通過spark.driver.extraJavaOptions設置加載log4j.properties文件的路徑,如:
spark.driver.extraJavaOptions -Dlog4j.configuration=file:/home/hadoop/ym/spark-1.6.1-bin-hadoop2.6/conf/log4j.properties
具體log4j.properties參考:
# Set everything to be logged to the console log4j.rootCategory=INFO, console,rolling log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.target=System.err log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{1}: %m%n # Settings to quiet third party logs that are too verbose log4j.logger.org.spark-project.jetty=WARN log4j.logger.org.spark-project.jetty.util.component.AbstractLifeCycle=ERROR log4j.logger.org.apache.spark.repl.SparkIMain$exprTyper=INFO log4j.logger.org.apache.spark.repl.SparkILoop$SparkILoopInterpreter=INFO log4j.logger.org.apache.parquet=ERROR log4j.logger.parquet=ERROR # SPARK-9183: Settings to avoid annoying messages when looking up nonexistent UDFs in SparkSQL with Hive support log4j.logger.org.apache.hadoop.hive.metastore.RetryingHMSHandler=FATAL log4j.logger.org.apache.hadoop.hive.ql.exec.FunctionRegistry=ERROR log4j.appender.rolling=org.apache.log4j.RollingFileAppender log4j.appender.rolling.layout=org.apache.log4j.PatternLayout log4j.appender.rolling.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} - [%p] - [%l] %m%n log4j.appender.rolling.Append=true log4j.appender.rolling.Encoding=UTF-8 log4j.appender.rolling.MaxBackupIndex=5 log4j.appender.rolling.MaxFileSize=200MB log4j.appender.rolling.file=/home/hadoop/ym/logs/${spark.app.name}.driver.log log4j.logger.org.apache.spark=INFO log4j.logger.org.eclipse.jetty=WARN
這樣的配置可以使Application的日志以AppName.driver.log的形式存放於你指定的目錄。
2)executor的日志,可以通過spark.executor.extraJavaOptions設置加載log4j.properties文件的路徑,如:
spark.executor.extraJavaOptions -Dlog4j.configuration=file:/home/hadoop/ym/spark-1.6.1-bin-hadoop2.6/conf/log4j-executor.properties
具體log4j.properties參考:
# Set everything to be logged to the console log4j.rootCategory=INFO,rolling log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.target=System.err log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{1}: %m%n # Settings to quiet third party logs that are too verbose log4j.logger.org.spark-project.jetty=WARN log4j.logger.org.spark-project.jetty.util.component.AbstractLifeCycle=ERROR log4j.logger.org.apache.spark.repl.SparkIMain$exprTyper=INFO log4j.logger.org.apache.spark.repl.SparkILoop$SparkILoopInterpreter=INFO log4j.logger.org.apache.parquet=ERROR log4j.logger.parquet=ERROR # SPARK-9183: Settings to avoid annoying messages when looking up nonexistent UDFs in SparkSQL with Hive support log4j.logger.org.apache.hadoop.hive.metastore.RetryingHMSHandler=FATAL log4j.logger.org.apache.hadoop.hive.ql.exec.FunctionRegistry=ERROR log4j.appender.rolling=org.apache.log4j.RollingFileAppender log4j.appender.rolling.layout=org.apache.log4j.PatternLayout log4j.appender.rolling.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} - [%p] - [%l] %m%n log4j.appender.rolling.Append=true log4j.appender.rolling.Encoding=UTF-8 log4j.appender.rolling.MaxBackupIndex=5 log4j.appender.rolling.MaxFileSize=2MB log4j.appender.rolling.file=${spark.yarn.app.container.log.dir}/stdout log4j.logger.org.apache.spark=DEBUG log4j.logger.org.eclipse.jetty=WARN 其中executor日志分為運行時日志以及結束日志,兩種日志分別存放於不同的位置,運行時候的日志文件存放於yarn.nodemanager.log−dirs/{ApplicationID},如: <property> <name>yarn.nodemanager.log-dirs</name> <value>file:/mnt/ddb/2/hadoop/nm</value> </property>
那么運行時候的executor日志存放於:
root@xxx:/mnt/ddb/2/hadoop/nm/application_1471515078641_0007# ls
container_1471515078641_0007_01_000001 container_1471515078641_0007_01_000002 container_1471515078641_0007_01_000003
其中container_1471515078641_0007_01_000001為RM為application_1471515078641_0007分配的第一個container,即AM所在的container,第一個container都是運來啟動AM的,containerID形式為,container_APPID_01_000001,你在RM日志文件里面根據container_APPID搜索即可看到為該APPID分配的container的分布情況及生命周期。
運行結束以后日志會聚合到HDFS上面去,具體路徑為/tmp/logs/${user}/logs,如:
drwxrwx--- - root supergroup 0 2016-08-18 18:29 /tmp/logs/root/logs/application_1471515078641_0002
drwxrwx--- - root supergroup 0 2016-08-18 19:10 /tmp/logs/root/logs/application_1471515078641_0003
drwxrwx--- - root supergroup 0 2016-08-18 19:17 /tmp/logs/root/logs/application_1471515078641_0004
3)am的日志配置,可以通過spark.yarn.am.extraJavaOptions設置加載log4j.properties文件的路徑,如:
spark.yarn.am.extraJavaOptions -Dlog4j.configuration=file:/home/hadoop/ym/spark-1.6.1-bin-hadoop2.6/conf/log4j-executor.properties
因為am和executor都是運行在container里面,具體log4j.properties可以參考executor的,這里不再多說。
補充一些:
下面重點說下,遇見spark問題該怎么去排查日志,都排查哪些日志,spark的運行流程可以參考http://ks.netease.com/blog?id=5174,這這邊每個過程都代表着不同的日志文件。
一,SC初始化的過程中出現問題的排查方式
1)driver提交到RM的時候,如果提交不上去,首先排查driver日志,其次根據APPID排查RM日志看下APP生命周期
2)RM啟動AM的過程出現問題,首先排查RM日志看為APP分配的第一個container下發到哪個NM上面去了,到對應的NM上面去根據containerID查看其生命周期哪里出現問題了
3)AM啟動了,向RM申請container的過程出現了問題,首先查看am的日志,即第一個container的日志,排查下都申請了哪些container,這些container都下發了哪些節點,然后到對應節點的NM日志上根據containerID查看其生命周期情況
4)executor啟動了,無法注冊到driver,這時候就要去查看對應的executor的日志
二,SC.action以后的問題排查
1)首先在driver日志里面去查看都有哪些job,哪些job failed了,然后找到failed的job,查看該job都有哪些stage,然后排查下那個stage失敗了,然后去查看該stage都有哪些task,哪個task失敗了,找到失敗的task下發的executor,然后去這個executor日志上,根據task id排查這個task的生命周期。
2)如果是executorLost的,除了要看這個executor的日志外,還要看這個container所在的nm日志,看下根據containerID看下器生命周期
3)如果是寫HDFS上出現問題了,首先排查nm日志,根據nm日志去排查出現問題的datanode日志。
中間有些由於自己理解的不事很好,可能存在問題,請見諒。
最后說一點,排查問題是學習的最好方式,排查完之后能深入了的明白原理,問題處理的越多,學習也就越快,每個人都是從一頭霧水走過來。
更多網易技術、產品、運營經驗分享請點擊。
相關文章:
【推薦】 如何玩轉基於風險的測試
【推薦】 InnoDB recovery過程解析