Yarn Cluster
- 执行脚本提交任务,实际是启动一个 SparkSubmit 的 JVM 进程;
- SparkSubmit 类中的 main 方法反射调用 YarnClusterApplication 的 main 方法;
- YarnClusterApplication 创建 Yarn 客户端,然后向 Yarn 服务器发送执行指令:bin/java ApplicationMaster;
- RM收到指令后,分配Container,在合适的 NM 中启动 ApplicationMaster;
- ApplicationMaster 启动 Driver 线程,执行用户的作业;
- AM 向 RM 注册,申请资源运行Executor;
- RM分配Container,获取资源后 AM 向 NM 发送指令:bin/java YarnCoarseGrainedExecutorBackend;
- CoarseGrainedExecutorBackend 进程会接收消息,启动Executor,启动后会和Driver反向注册,Executor 等待接收任务。Executor全部注册完成后Driver开始执行main函数
- Driver 线程继续执行,完成作业的调度和任务的执行。
- Driver 分配任务并监控任务的执行。
【之后执行到 Action 算子时,触发一个 Job,并根据宽依赖开始划分 stage,每个 stage 生 成对应的 TaskSet,之后将 task 分发到各个 Executor 上执行。】
YARN Client 模式
-
执行脚本提交任务,实际是启动一个 SparkSubmit 的 JVM 进程;
-
SparkSubmit 类中的 main 方法反射调用用户代码的 main 方法;
-
启动 Driver 线程,执行用户的作业,并创建 ScheduleBackend;
-
YarnClientSchedulerBackend 向 RM 发送指令:bin/java ExecutorLauncher;
-
RM收到指令后,分配Container,在合适的 NM 中启动 ExecutorLauncher(实际上还是调用ApplicationMaster 的 main 方法);
object ExecutorLauncher {
def main(args: Array[String]): Unit = {
ApplicationMaster.main(args)
}
}
- AM 向 RM 注册,申请资源运行Excutor;
- RM分配Container,获取资源后 AM 向 NM 发送指令:bin/java CoarseGrainedExecutorBackend;
- CoarseGrainedExecutorBackend 进程会接收消息,启动的Executor,启动后会向 Driver 反向注册,Executor 等待接收任务。Executor 全部注册完成后 Driver 开始执行main 函数,
- 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执行用户代码的内存不够用,那么同样建议调低这个参数的值。