Spark On Yarn

146 阅读3分钟

Yarn Cluster

1.png

  1. 执行脚本提交任务,实际是启动一个 SparkSubmit 的 JVM 进程;
  2. SparkSubmit 类中的 main 方法反射调用 YarnClusterApplication 的 main 方法;
  3. YarnClusterApplication 创建 Yarn 客户端,然后向 Yarn 服务器发送执行指令:bin/java ApplicationMaster;
  4. RM收到指令后,分配Container,在合适的 NM 中启动 ApplicationMaster;
  5. ApplicationMaster 启动 Driver 线程,执行用户的作业;
  6. AM 向 RM 注册,申请资源运行Executor;
  7. RM分配Container,获取资源后 AM 向 NM 发送指令:bin/java YarnCoarseGrainedExecutorBackend;
  8. CoarseGrainedExecutorBackend 进程会接收消息,启动Executor,启动后会和Driver反向注册,Executor 等待接收任务。Executor全部注册完成后Driver开始执行main函数
  9. Driver 线程继续执行,完成作业的调度和任务的执行。
  10. Driver 分配任务并监控任务的执行。

【之后执行到 Action 算子时,触发一个 Job,并根据宽依赖开始划分 stage,每个 stage 生 成对应的 TaskSet,之后将 task 分发到各个 Executor 上执行。】

YARN Client 模式

  1. 执行脚本提交任务,实际是启动一个 SparkSubmit 的 JVM 进程;

  2. SparkSubmit 类中的 main 方法反射调用用户代码的 main 方法;

  3. 启动 Driver 线程,执行用户的作业,并创建 ScheduleBackend;

  4. YarnClientSchedulerBackend 向 RM 发送指令:bin/java ExecutorLauncher;

  5. RM收到指令后,分配Container,在合适的 NM 中启动 ExecutorLauncher(实际上还是调用ApplicationMaster 的 main 方法);

object ExecutorLauncher {
 def main(args: Array[String]): Unit = {
 ApplicationMaster.main(args)
 }
}
  1. AM 向 RM 注册,申请资源运行Excutor;
  2. RM分配Container,获取资源后 AM 向 NM 发送指令:bin/java CoarseGrainedExecutorBackend;
  3. CoarseGrainedExecutorBackend 进程会接收消息,启动的Executor,启动后会向 Driver 反向注册,Executor 等待接收任务。Executor 全部注册完成后 Driver 开始执行main 函数,
  4. Driver 分配任务并监控任务的执行。

spark-submit参数

spark.storage.memoryFraction

参数说明:该参数用于设置RDD持久化数据在Executor内存中能占的比例,默认是0.6。也就是说,默认Executor 60%的内存,可以用来保存持久化的RDD数据。根据你选择的不同的持久化策略,如果内存不够时,可能数据就不会持久化,或者数据会写入磁盘。

参数调优建议:如果Spark作业中,有较多的RDD持久化操作,该参数的值可以适当提高一些,保证持久化的数据能够容纳在内存中。避免内存不够缓存所有的数据,导致数据只能写入磁盘中,降低了性能。但是如果Spark作业中的shuffle类操作比较多,而持久化操作比较少,那么这个参数的值适当降低一些比较合适。此外,如果发现作业由于频繁的gc导致运行缓慢(通过spark web ui可以观察到作业的gc耗时),意味着task执行用户代码的内存不够用,那么同样建议调低这个参数的值spark.shuffle.memoryFraction

参数说明:该参数用于设置shuffle过程中一个task拉取到上个stage的task的输出后,进行聚合操作时能够使用的Executor内存的比例,默认是0.2。也就是说,Executor默认只有20%的内存用来进行该操作。shuffle操作在进行聚合时,如果发现使用的内存超出了这个20%的限制,那么多余的数据就会溢写到磁盘文件中去,此时就会极大地降低性能。 参数调优建议:如果Spark作业中的RDD持久化操作较少,shuffle操作较多时,建议降低持久化操作的内存占比,提高shuffle操作的内存占比比例,避免shuffle过程中数据过多时内存不够用,必须溢写到磁盘上,降低了性能。此外,如果发现作业由于频繁的gc导致运行缓慢,意味着task执行用户代码的内存不够用,那么同样建议调低这个参数的值