文章目录
Monitoring and Instrumentation (监控和测量)
有几种方式去监控Spark applications,如web UIs、metrics及external instrumentation。
Web Interfaces(web界面)
Every SparkContext launches a web UI, by default on port 4040, that displays useful information about the application
每个SparkContext
都会启动一个web UI(一个SparkContext就对应着一个driver program
),端口默认是4040,web界面会展示如下有用的信息:
- schedule过程中stage和tasks的列表
- RDD大小和内存使用情况的统计
- 环境信息
- 当前正在执行任务的executors信息
可以通过 http://<driver-node>:4040
来访问web界面,如果有多个SparkContext
在同一个机器上即一个机器上有多个driver program
,它们会绑定连续的端口,从4040开始,如4041、4042等。
注意这个信息只能在application在运行时获得,因为application完成后driver program
就完成了,就不会存在该driver program
对应的web接口。所以为了能在application完成后还能看到这个web UI,必须要在application开始前给该application设置 spark.eventLog.enabled=true
,该property会使Spark Application将UI中显示的信息编码为spark events并记录spark events到持久化存储里。
Viewing After the Fact (事后查看)
如果application的spark events
存在的话可以通过启动spark history server来查看application对应的UI界面。可以通过 ./sbin/start-history-server.sh
来启动spark history server。该命令会在当前机器上启动一个进程,可通过 http://<server-url>:18080
来访问。
当使用 file-system provider class
(即下面的配置参数spark.history.provider
)时,必须要设置 spark.history.fs.logDirectory
来指定logging directory。
注意:spark application必须要配置来记录spark events并将其记录到指定目录,例如,假设history服务端配置了参数spark.history.fs.logDirectory=hdfs://namenode/shared/spark-logs
,那么client端在提交任务时需要设置如下两个参数
spark.eventLog.enabled true
spark.eventLog.dir hdfs://namenode/shared/spark-logs
命令如下
spark-submit --conf spark.eventLog.enabled=true \
--conf spark.eventLog.dir=hdfs://namenode/shared/spark-logs \
--master yarn --deploy-mode cluster \
--class org.apache.spark.examples.SparkPi \
/usr/local/src/spark/examples/jars/spark-examples_2.11-2.4.5.jar 100
spark history server可以配置如下参数信息
Environment Variables
环境变量,可在${SPARK_HOME}/conf/spark-env.sh
文件里修改
Environment Variable | Meaning |
---|---|
SPARK_DAEMON_MEMORY | 分配给history server的内存 (default: 1g). |
SPARK_DAEMON_JAVA_OPTS | history server的JVM参数 (default: none). |
SPARK_DAEMON_CLASSPATH | history server的classpath (default: none). |
SPARK_PUBLIC_DNS | history server的公共地址。如果没设置默认使用服务的内部地址,有可能造成broken lines. (default: none). |
SPARK_HISTORY_OPTS | 专门为history server设置的properties,如-Dx=y (default: none). |
Spark History Server Configuration Options
spark history server的配置选项,可在${SPARK_HOME}/conf/spark-defaults.conf
文件里修改
Property Name | Default | Meaning |
---|---|---|
spark.history.provider | org.apache.spark.deploy.history.FsHistoryProvider | 实现application history后台的类的名称,目前只有一个由Spark提供的实现,用于查找存储在文件系统中的application log. |
spark.history.fs.logDirectory | file:/tmp/spark-events | 对于文件系统history provider, 存放application event log的目录的URL。可以是本地文件file://path, 也可以是HDFS路径hdfs://namenode/shared/spark-logs, 也可以是Hadoop API支持的其他文件系统. |
spark.history.fs.update.interval | 10s | 文件系统history provider检查日志目录中新日志或更新日志的周期。更短的间隔可以更快地检测到新的application,但代价是需要更多的服务器负载来重新读取更新的application。一旦更新完成,已完成和未完成的applicaiton的列表将会改变。 |
spark.history.retainedApplications | 50 | 在缓存中保留UI数据的application的数量。如果超过这个上限, 那么最老的application将从缓存中删除。如果application不在缓存中那么从UI访问它时则必须从磁盘加载它. |
spark.history.ui.maxApplications | Int.MaxValue | 在history summary页上显示的application数量。即时applicaiton没有显示在history summary页上, 仍然可以通过直接访问它们的url来访问。 |
spark.history.ui.port | 18080 | history server的web界面绑定的端口 |
spark.history.fs.cleaner.enabled | false | history server是否需要定期从存储里面删除event log |
spark.history.fs.cleaner.interval | 1d | 文件系统的history cleaner程序检查哪些文件需要删除的频率。只有当文件时间大于spark.history.fs.cleaner.maxAge时才会被删除 |
spark.history.fs.cleaner.maxAge | 7d | 当文件系统的history cleaner程序运行时大于该值的文件会被删除 |
spark.history.fs.endEventReparseChunkSize | 1m | How many bytes to parse at the end of log files looking for the end event. 通过跳过event log文件中非必要的部分来加速application的list的生成, 可以设置0来禁用它. |
spark.history.fs.inProgressOptimization.enabled | true | 启用对正在处理的日志的优化处理。此选项可能会使完成的应用程序无法将其事件日志重命名为“进行中”。 |
spark.history.fs.numReplayThreads | 25% of available cores | history server用来处理event log的线程数 |
spark.history.store.maxDiskUsage | 10g | 存储cache application历史信息的本地目录的最大磁盘使用量。 |
spark.history.store.path | (none) | Local directory where to cache application history data. If set, the history server will store application data on disk instead of keeping it in memory. The data written to disk will be re-used in the event of a history server restart. |
REST API
具体信息可参考官网 REST API
Executor Task Metrics
具体信息可参考官网 Executor Task Metrics
配置例子
存储在本地文件系统
以application event log存储在本地文件系统为例,可以联想MapReduce Job History Server的配置。
需要在所有的计算节点(如果是spark on yarn模式那就是所有的nodemanager节点),配置好相应的spark-env.sh
、spark-defaults.conf
文件。
spark-env.sh
文件内容如下
HADOOP_HOME=/usr/local/src/hadoop
SPARK_HOME=/usr/local/src/spark
HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
YARN_CONF_DIR=$HADOOP_HOME/etc/hadoop
SPARK_PID_DIR=${SPARK_HOME}/pids
spark-defaults.conf
文件内容如下,注意/tmp/spark_logs
目录需要提前创建
spark.history.fs.logDirectory file:///tmp/spark_logs
在所有的节点安装好spark,修改好对应的文件,提前创建好目录后,就可以在每个计算节点启动spark history server
启动 ./sbin/start-history-server.sh
关闭 ./sbin/stop-history-server.sh
我们将spark提供的例子提交到yarn上,命令如下
spark-submit --conf spark.eventLog.enabled=true \
--conf spark.eventLog.dir=hdfs://namenode/shared/spark-logs \
--master yarn --deploy-mode cluster \
--class org.apache.spark.examples.SparkPi \
/usr/local/src/spark/examples/jars/spark-examples_2.11-2.4.5.jar 100
当application完成后然后可以在对应的历史任务上看到
注意,当在yarn-site.xml
文件里开启了yarn.timeline-service.enabled=true
后,在提交Application给Spark时可能会报错java.lang.NoClassDefFoundError: com/sun/jersey/api/client/config/ClientConfig
,这是由于YARN用的是 Jersey 1但是Spark 2.0用的是 Jersey 2。如下图所示
解决方法就是在 spark-defaults.conf
文件里添加spark.hadoop.yarn.timeline-service.enabled false
,如下图所示。
存储在HDFS文件系统
如果将application event log存储在HDFS文件系统,那么只需要将上面的 file:///tmp/spark_logs
改为hdfs路径如hdfs://master:9000/tmp/spark_logs
,同样地hdfs上的路径/tmp/spark_logs
需要预先创建好。
同时用spark-submit提交任务时改为--conf spark.eventLog.dir=hdfs://master:9000/tmp/spark_logs
即可。
这样的话就只用启动一个Spark History server了,不要像存储在本地文件系统一样需要在每个计算节点都启动相应的服务。
history server日志会很大的问题
查看history server的启动脚本可知,history server 启动的时候使用了默认的 log4j.properties 文件里面的配置,用的是org.apache.log4j.ConsoleAppender
,导致每次只有重启 HistoryServer 的时候才会重新生成一个新的日志文件而且滚动文件最多只有5个(看spark-daemon.sh脚本的spark_rotate_log
),如果不重启 HistoryServer,日志文件会无限制的增长下去,久而久之导致存放 HistoryServer 日志的文件夹越来越大。
解决方案就是启用新的log4j.properties文件,改成org.apache.log4j.RollingFileAppender
,内容如下
# 设置historyserver的日志大小
log4j.logger.org.apache.spark.deploy.history=info,historyserver
# 这样信息就不会输出到父logger
log4j.additivity.org.apache.spark.deploy.history=false
log4j.appender.historyserver=org.apache.log4j.RollingFileAppender
log4j.appender.historyserver.layout=org.apache.log4j.PatternLayout
log4j.appender.historyserver.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{1}: %m%n
log4j.appender.historyserver.MaxFileSize=1GB
log4j.appender.historyserver.MaxBackupIndex=7
log4j.appender.historyserver.File=/usr/local/src/spark/logs/historyserver.log
参考网址
Spark Monitoring
spark history server日志文件过大报警
jersey problem