文章目录

  • 一 Spark内核概述
  • 1 Spark核心组件回顾
  • (1)Driver
  • (2)Executor
  • 2 Spark通用运行流程概述
  • 二 Spark部署模式
  • 1 YARN模式运行机制
  • (1)YARNCluster模式
  • (2)YARN Client模式
  • 2 Standalone模式运行机制
  • (1)Standalone Cluster模式
  • (2)Standalone Client模式
  • 三 Spark通讯架构
  • 1 Spark通信架构概述
  • 2 Spark通讯架构解析


一 Spark内核概述

Spark内核泛指Spark的核心运行机制,包括Spark核心组件的运行机制、Spark任务调度机制、Spark内存管理机制、Spark核心功能的运行原理等,熟练掌握Spark内核原理,能够帮助我们更好地完成Spark代码设计,并能够帮助我们准确锁定项目运行过程中出现的问题的症结所在。

1 Spark核心组件回顾

(1)Driver

Spark驱动器节点,用于执行Spark任务中的main方法,负责实际代码的执行工作。Driver在Spark作业执行时主要负责:

将用户程序转化为作业(Job);
在Executor之间调度任务(Task);
跟踪Executor的执行情况;
通过UI展示查询运行情况;

(2)Executor

Spark Executor对象是负责在Spark作业中运行具体任务,任务彼此之间相互独立。Spark 应用启动时,ExecutorBackend节点被同时启动,并且始终伴随着整个Spark应用的生命周期而存在。如果有ExecutorBackend节点发生了故障或崩溃,Spark应用也可以继续执行,会将出错节点上的任务调度到其他Executor节点上继续运行。

Executor有两个核心功能:

负责运行组成Spark应用的任务,并将结果返回给驱动器(Driver);
它们通过自身的块管理器(Block Manager)为用户程序中要求缓存的 RDD 提供内存式存储。RDD是直接缓存在Executor进程内的,因此任务可以在运行时充分利用缓存数据加速运算。

2 Spark通用运行流程概述

spark etl工具 sparktec_spark

上图为Spark通用运行流程图,体现了基本的Spark应用程序在部署中的基本提交流程。

这个流程是按照如下的核心步骤进行工作的:

任务提交后,都会先启动Driver程序;
随后Driver向集群管理器注册应用程序;
之后集群管理器根据此任务的配置文件分配Executor并启动;
Driver开始执行main函数【在资源满足之前也会执行main方法去准备Spark Context环境】,Spark查询为懒执行,当执行到Action算子时开始反向推算,根据宽依赖进行Stage的划分,随后每一个Stage对应一个Taskset,Taskset中有多个Task,查找可用资源Executor进行调度;
根据本地化原则,Task会被分发到指定的Executor去执行,在任务执行的过程中,Executor也会不断与Driver进行通信,报告任务运行情况。

二 Spark部署模式

Spark支持多种集群管理器(Cluster Manager),分别为:

Standalone:独立模式,Spark原生的简单集群管理器,自带完整的服务,可单独部署到一个集群中,无需依赖任何其他资源管理系统,使用Standalone可以很方便地搭建一个集群;
Hadoop YARN:统一的资源管理机制,在上面可以运行多套计算框架,如MR、Storm等。根据Driver在集群中的位置不同,分为yarn client(集群外)和yarn cluster(集群内部)
Apache Mesos:一个强大的分布式资源管理框架,它允许多种不同的框架部署在其上,包括Yarn。
K8S : 容器式部署环境。

实际上,除了上述这些通用的集群管理器外,Spark内部也提供了方便用户测试和学习的本地集群部署模式和Windows环境。由于在实际工厂环境下使用的绝大多数的集群管理器是Hadoop YARN,因此关注的重点是Hadoop YARN模式下的Spark集群部署。

1 YARN模式运行机制

(1)YARNCluster模式

执行脚本提交任务,实际是启动一个SparkSubmit的 JVM进程;
SparkSubmit类中的main方法反射调用YarnClusterApplication的main方法;
YarnClusterApplication创建Yarn客户端,然后向Yarn服务器发送执行指令:bin/java ApplicationMaster;
Yarn框架收到指令后会在指定的NM中启动ApplicationMaster;
ApplicationMaster启动Driver线程,执行用户的作业;
AM向RM注册,申请资源;
获取资源后AM向NM发送指令:bin/java YarnCoarseGrainedExecutorBackend;
CoarseGrainedExecutorBackend进程会接收消息,跟Driver通信,注册已经启动的Executor;然后启动计算对象Executor等待接收任务
Driver线程继续执行完成作业的调度和任务的执行。
  1. Driver分配任务并监控任务的执行。

注意:SparkSubmit、ApplicationMaster和CoarseGrainedExecutorBackend是独立的进程;Driver是独立的线程;Executor和YarnClusterApplication是对象。

(2)YARN Client模式

执行脚本提交任务,实际是启动一个SparkSubmit的JVM进程;
SparkSubmit类中的main方法反射调用用户代码的main方法;
启动Driver线程,执行用户的作业,并创建ScheduleBackend;
YarnClientSchedulerBackend向RM发送指令:bin/java ExecutorLauncher;
Yarn框架收到指令后会在指定的NM中启动ExecutorLauncher(实际上还是调用ApplicationMaster的main方法);
object ExecutorLauncher {
  def main(args: Array[String]): Unit = {
    ApplicationMaster.main(args)
  }
}
AM向RM注册,申请资源;
获取资源后AM向NM发送指令:bin/java CoarseGrainedExecutorBackend;
CoarseGrainedExecutorBackend进程会接收消息,跟Driver通信,注册已经启动的Executor;然后启动计算对象Executor等待接收任务
Driver分配任务并监控任务的执行。

注意:SparkSubmit、ApplicationMaster和YarnCoarseGrainedExecutorBackend是独立的进程;Executor和Driver是对象。

spark etl工具 sparktec_spark etl工具_02

2 Standalone模式运行机制

Standalone集群有2个重要组成部分,分别是:

Master(RM):是一个进程,主要负责资源的调度和分配,并进行集群的监控等职责;

2) Worker(NM):是一个进程,一个Worker运行在集群中的一台服务器上,主要负责两个职责,一个是用自己的内存存储RDD的某个或某些partition;另一个是启动其他进程和线程(Executor),对RDD上的partition进行并行的处理和计算。

(1)Standalone Cluster模式

spark etl工具 sparktec_spark etl工具_03

在Standalone Cluster模式下,任务提交后,Master会找到一个Worker启动Driver。Driver启动后向Master注册应用程序,Master根据submit脚本的资源需求找到内部资源至少可以启动一个Executor的所有Worker,然后在这些Worker之间分配Executor,Worker上的Executor启动后会向Driver反向注册,所有的Executor注册完成后,Driver开始执行main函数,之后执行到Action算子时,开始划分Stage,每个Stage生成对应的taskSet,之后将Task分发到各个Executor上执行。

(2)Standalone Client模式

spark etl工具 sparktec_架构_04

在Standalone Client模式下,Driver在任务提交的本地机器上运行。Driver启动后向Master注册应用程序,Master根据submit脚本的资源需求找到内部资源至少可以启动一个Executor的所有Worker,然后在这些Worker之间分配Executor,Worker上的Executor启动后会向Driver反向注册,所有的Executor注册完成后,Driver开始执行main函数,之后执行到Action算子时,开始划分Stage,每个Stage生成对应的TaskSet,之后将Task分发到各个Executor上执行。

三 Spark通讯架构

1 Spark通信架构概述

Spark中通信框架的发展:

  • Spark早期版本中采用Akka作为内部通信部件。
  • Spark1.3中引入Netty通信框架,为了解决Shuffle的大数据传输问题使用
  • Spark1.6中Akka和Netty可以配置使用。Netty完全实现了Akka在Spark中的功能。
  • Spark2系列中,Spark抛弃Akka,使用Netty。

Spark2.x版本使用Netty通讯框架作为内部通讯组件。Spark 基于Netty新的RPC框架借鉴了Akka中的设计,它是基于Actor模型,如下图所示:

spark etl工具 sparktec_大数据_05

Spark通讯框架中各个组件(Client/Master/Worker)可以认为是一个个独立的实体,各个实体之间通过消息来进行通信。具体各个组件之间的关系图如下:

spark etl工具 sparktec_spark_06

Endpoint(Client/Master/Worker)有1个InBox和N个OutBox(N>=1,N取决于当前Endpoint与多少其他的Endpoint进行通信,一个与其通讯的其他Endpoint对应一个OutBox),Endpoint接收到的消息被写入InBox,发送出去的消息写入OutBox并被发送到其他Endpoint的InBox中。

Spark通信终端

Driver:

class DriverEndpoint extends IsolatedRpcEndpoint

Executor

class CoarseGrainedExecutorBackend extends IsolatedRpcEndpoint

2 Spark通讯架构解析

Spark通信架构如下图所示:

spark etl工具 sparktec_架构_07

  • RpcEndpoint:RPC通信终端。Spark每个节点(Client/Master/Worker)都称之为一个RPC终端,且都实现RpcEndpoint接口,内部根据不同端点的需求,设计不同的消息和不同的业务处理,如果需要发送(询问)则调用Dispatcher。在Spark中,所有的终端都存在生命周期:
  • Constructor
  • onStart
  • receive*
  • onStop
  • RpcEnv:RPC上下文环境,每个RPC终端运行时依赖的上下文环境称为RpcEnv;在把当前Spark版本中使用的NettyRpcEnv
  • Dispatcher:消息调度(分发)器,针对于RPC终端需要发送远程消息或者从远程RPC接收到的消息,分发至对应的指令收件箱(发件箱)。如果指令接收方是自己则存入收件箱,如果指令接收方不是自己,则放入发件箱;
  • Inbox:指令消息收件箱。一个本地RpcEndpoint对应一个收件箱,Dispatcher在每次向Inbox存入消息时,都将对应EndpointData加入内部ReceiverQueue中,另外Dispatcher创建时会启动一个单独线程进行轮询ReceiverQueue,进行收件箱消息消费;
  • RpcEndpointRef:RpcEndpointRef是对远程RpcEndpoint的一个引用。当需要向一个具体的RpcEndpoint发送消息时,一般需要获取到该RpcEndpoint的引用,然后通过该应用发送消息。
  • OutBox:指令消息发件箱。对于当前RpcEndpoint来说,一个目标RpcEndpoint对应一个发件箱,如果向多个目标RpcEndpoint发送信息,则有多个OutBox。当消息放入Outbox后,紧接着通过TransportClient将消息发送出去。消息放入发件箱以及发送过程是在同一个线程中进行;
  • RpcAddress:表示远程的RpcEndpointRef的地址,Host + Port。
  • TransportClient:Netty通信客户端,一个OutBox对应一个TransportClient,TransportClient不断轮询OutBox,根据OutBox消息的receiver信息,请求对应的远程TransportServer;
  • TransportServer:Netty通信服务端,一个RpcEndpoint对应一个TransportServer,接受远程消息后调用Dispatcher分发消息至对应收发件箱;