第1章 对运行在YARN上的Spark进行性能调优

第1章  对运行在YARN上的Spark进行性能调优

1.1      运行环境Jar包管理及数据本地性原理调优实践

1.1.1运行环境Jar包管理及和数据本地性原理

在YARN上运行Spark需要在Spark-env.sh或环境变量中配置HADOOP_CONF_DIR或YARN_CONF_DIR目录指向Hadoop的配置文件。

Spark-default.conf中配置Spark.YARN.jars指向hdfs上的Spark需要的jar包。如果不配置该参数,每次启动Spark程序将会将Driver端的SPARK_HOME打包上传分发到各个节点。配置如下例所示:

1.          spark.yarn.jarshdfs://clustername/spark/spark210/jars/*

 

对于分布式系统来说,由于数据可能也是分布式的,所以数据处理往往也是分布式的。要想保证性能,尽量保证数据本地性是很重要的。

分布式计算系统的精粹在于移动计算而非移动数据,但是在实际的计算过程中,总存在着移动数据的情况,除非是在集群的所有节点上都保存数据的副本。移动数据,将数据从一个节点移动到另一个节点进行计算,不但消耗了网络IO,也消耗了磁盘IO,降低了整个计算的效率。为了提高数据的本地性,除了优化算法(也就是修改Spark内存,难度有点高),就是合理设置数据的副本。设置数据的副本,这需要通过配置参数并长期观察运行状态才能获取的一个经验值。

 

Spark中的数据本地性有以下几种:

l  PROCESS_LOCAL:进程本地化。代码和数据在同一个进程中,也就是在同一个Executor中;计算数据的Task由Executor执行,数据在Executor的BlockManager中;性能最好。

l  NODE_LOCAL:节点本地化:代码和数据在同一个节点中,数据作为一个HDFS block块,就在节点上,而Task在节点上某个Executor中运行;或者是数据和Task在一个节点上的不同Executor中;数据需要在进程间进行传输。也就是说,数据虽然在同一Worker 中, 但不是同一JVM中。这隐含着进程间移动数据的开销。

l  NO_PREF:数据没有局部性首选位置, 它能从任何位置同等访问。对于Task来说,数据从哪里获取都一样,无好坏之分。

l  RACK_LOCAL:机架本地化。数据在不同的服务器上,但在相同的机架。数据需要通过网络在节点之间进行传输。

l  ANY:数据在不同的服务器及机架上面。这种方式性能最差。

 

Spark应用程序运行本身包含代码和数据两部分,单机版本一般情况下很少考虑数据本地性的问题,因为数据在本地。单机版本的程序,数据本性有PROCESS_LOCAL和NODE_LOCAL之分,但也应尽量让数据处于PROCESS_LOCAL级别。

通常,读取数据要尽量使数据以PROCESS_LOCAL或NODE_LOCAL方式读取。其中PROCESS_LOCAL还和Cache有关,如果RDD经常用的话,应将该RDD Cache到内存中。注意,由于Cache是Lazy级别的,所以必须通过一个Action的触发,才能真正的将该RDD Cache到内存中。

1.1.2运行环境Jar包管理及数据本地性调优实践

启动Spark程序时,其他节点会自动去下载这些包并进行缓存,下次启动如果包没有变化则会直接读取本地缓存的包。缓存清理间隔在YARN-site.xml通过以下参数配置:

1.           yarn.nodemanager.localizer.cache.cleanip.interval-ms

 

启动Spark-Shell,指定master为YARN,默认为client模式。在cluster模式下可以使用—supervise,如果Driver异常退出将会自行重启。

1.         /usr/install/Spark210/bin/Spark-Shell

2.         --master YARN

3.         --deploy-mode client

4.         --Executor-memory 1g

5.         --Executor-cores 1

6.         --Driver-memory 1g

7.         --queue test (默认队列是default)

 

初次讲到参数配置,需要提醒的是在代码中的SparkConf中的配置参数具有最高优先级,其次是Spark-Submit或Spark-Shell的参数,最后是配置文件(conf/Spark-defaults.conf)中的参数。

本地性级别是以最近的级别开始,以最远的级别结束。Spark 调度任务执行是要让任务获得最近的本地性级别的数据。然而,有时候它不得不放弃最近本地性级别, 因为一些资源上的原因,有时不得不选择更远的。在数据与Executor 在同一机器但是数据处理比较忙的情况下, 且存在一些空闲的Executor 远离数据的情况下, Spark会让Executor 等特定的时间,看其能否完成正在处理的工作。如果该Executor仍不可用, 一个新的任务将则启用在更远的可用节点上。即数据被传送给那个节点。

可以给Spark中的Executor配置单种数据本地性级别可以等待的空闲时长。如下例所示:

1.         Val SparkConf = new SparkConf()

2.         SparkConf.set("Spark.locality.wait","3s")

3.         SparkConf.set("Spark.locality.wait.node","3s")

4.         SparkConf.set("Spark.locality.wait.process","3s")

5.         SparkConf.set("Spark.locality.wait.rack","3s")

 

默认情况下,这些等待时长都是3秒。下面讲解调节这个参数的方式。推荐大家在测试的时候,先用Client模式,在本地就直接可以看到比较全的日志。观察日志Spark作业的运行日志。

里面会显示如下日志:

1.          17/02/11 21:59:45 INFOscheduler.TaskSetManager: Starting Task 0.0 in Stage 0.0 (TID 0, sandbox,PROCESS_LOCAL, 1260 bytes)

 

观察大部分Task的数据本地化级别:如果大多都是PROCESS_LOCAL,那就不用调节了;如果发现,很多的级别都是NODE_LOCAL、ANY,那么最好就去调节一下数据本地化的等待时长。调节往往不可能一次到位,应该是要反复调节,每次调节完以后,再来运行,观察日志。看看大部分的Task的本地化级别有没有提升;也看看整个Spark作业的运行时间有没有缩短。但别本末倒置,如果本地化级别提升了,但是因为大量的等待时长而导致Spark作业的运行时间反而增加,那也是不好的调节。

你可能感兴趣的:(SparkInBeiJing)