Spark源码解析(一)Spark RPC分析

通过学习Spark源码为了更深入的了解Spark。主要按照以下流程进行Spark的源码分析,包含了Spark集群的启动以及任务提交的执行流程:

  1. Spark RPC分析
  2. start-all.sh
  3. Master启动分析
  4. Work启动分析
  5. spark-submit.sh脚本分析
  6. SparkSubmit分析
  7. SparkContext初始化

1.Spark RPC分析

1.1.概述

了解Spark分布式集群的执行流程,那就不得不从Spark的网络通信说起,例如:

  • driver和master的通信,比如driver会想master发送RegisterApplication消息
  • master和worker的通信,比如worker会向master上报worker上运行Executor信息
  • executor和driver的的通信,executor运行在worker上,spark的tasks被分发到运行在各个
  • executor中,executor需要通过向driver发送任务运行结果。
  • worker和worker的通信,task运行期间需要从其他地方fetch数据,这些数据是由运行在其他worker上的executor上的task产生,因此需要到worker上fetch数据

总的说来,Spark通信主要存在于两个方面:

  1. 汇集信息,例如task变化信息,executor状态变化信息。
  2.  传输数据,spark shuffle(也就是reduce从上游map的输出中汇集输入数据)阶段存在大量的数据传输。

Spark通信框架版本更迭:

Spark 1.6之前,Spark 的 RPC 是基于 Akaa 来实现的。Akka 是一个基于 scala 语言的异步的消息框架。Spark1.6 后,Spark 借鉴 Akka 的设计自己实现了一个基于 Netty 的 rpc 框架。大概的原因是 1.6之前,RPC 通过 Akka 来实现,而大文件是基于 netty 来实现的,加之akka 版本兼容性问题,所以 1.6之后把 Akka 改掉了。

Spark早期版本中使用Netty通信框架做数据的传输,使用Akka用作RPC通信。

Spark 官网文档对此的描述为:“Akka 的依赖被移除了,因此用户可以使用任何版本的 Akka 来编程了。”Spark 团队的决策者或许认为对于 Akka 具体版本的依赖,限制了用户对于 Akka 不同版本的使用。

1.2.Spark的RPC组成

spark 基于netty新的rpc框架借鉴了Akka的中的设计,它是基于Actor模型,各个组件可以认为是一个个独立的实体,各个实体之间通过消息来进行通信。

  1. RpcEndPonit 和 RpcCallContext
    1. RpcEndPoint 是一个可以相应请求的服务,类似于 Akka 中的 Actor。表示一个个需要通信的个体(如master,worker,driver),主要根据接收的消息来进行对应的处理。一个RpcEndpoint经历的过程依次是:构建 -> onStart -> receive -> onStop。其中onStart在接收任务消息前调用,receive和receiveAndReply分别用来接收另一个RpcEndpoint(也可以是本身)send和ask过来的消息。
  2. RpcEndpointRef
    1. 类似于 Akka 中的 ActorRef,是 RpcEndPoint 的引用,持有远程 RpcEndPoint 的地址名称等,提供了 send 方法和 ask 方法用于发送请求。RpcEndpointRef 是对远程 RpcEndpoint 的一个引用。当我们需要向一个具体的 RpcEndpoint 发送消息时,一般我们需要获取到该 RpcEndpoint 的引用,然后通过该引用发送消息。
  3. RpcEnv 和 NettyRpcEnv
    1. RpcEnv 类似于 ActorSystem,服务端和客户端都可以使用它来做通信。
    2. 对于 server 端来说,RpcEnv 是 RpcEndpoint 的运行环境,负责 RpcEndPoint 的生命周期管理,解析 Tcp 层的数据包以及反序列化数据封装成 RpcMessage,然后根据路由传送到对应的 Endpoint;
    3. 对于 client 端来说,可以通过 RpcEnv 获取 RpcEndpoint 的引用,也就是 RpcEndpointRef,然后通过 RpcEndpointRef 与对应的 Endpoint 通信。
    4. RpcEnv 为 RpcEndpoint 提供处理消息的环境。RpcEnv 负责 RpcEndpoint 整个生命周期的管理,包括:注册endpoint,endpoint 之间消息的路由,以及停止 endpoint。
  4. Dispacher 与 Inbox 与 Outbox
    1. NettyRpcEnv 中包含 Dispatcher,主要针对服务端,帮助路由到指定的 RpcEndPoint,并调用起业务逻辑。
    2. RpcEndpoint:RPC端点 ,Spark针对于每个节点(Client/Master/Worker)都称之一个Rpc端点 ,且都实现RpcEndpoint接口,内部根据不同端点的需求,设计不同的消息和不同的业务处理,如果需要发送(询问)则调用Dispatcher
    3. Dispatcher:消息分发器,针对于RPC端点需要发送消息或者从远程RPC接收到的消息,分发至对应的指令收件箱/发件箱。如果指令接收方是自己存入收件箱,如果指令接收方为非自身端点,则放入发件箱
    4. Inbox:指令消息收件箱,一个本地端点对应一个收件箱,Dispatcher在每次向Inbox存入消息时,都将对应EndpointData加入内部待Receiver Queue中,另外Dispatcher创建时会启动一个单独线程进行轮询Receiver Queue,进行收件箱消息消费
    5. OutBox:指令消息发件箱,一个远程端点对应一个发件箱,当消息放入Outbox后,紧接着将消息通过TransportClient发送出去。消息放入发件箱以及发送过程是在同一个线程中进行,这样做的主要原因是远程消息分为RpcOutboxMessage, OneWayOutboxMessage两种消息,而针对于需要应答的消息直接发送且需要得到结果进行处理
    6. TransportClient:Netty通信客户端,根据OutBox消息的receiver信息,请求对应远程TransportServer
    7. TransportServer:Netty通信服务端,一个RPC端点一个TransportServer,接受远程消息后调用Dispatcher分发消息至对应收发件箱

核心要点如下:

  1. 核心的 RpcEnv 是一个特质(trait),它主要提供了停止,注册,获取 endpoint 等方法的定义,而NettyRpcEnv 提供了该特质的一个具体实现。
  2. 通过工厂 RpcEnvFactory 来产生一个 RpcEnv,而 NettyRpcEnvFactory 用来生成 NettyRpcEnv 的一个对象。
  3. 当我们调用 RpcEnv 中的 setupEndpoint 来注册一个 endpoint 到 rpcEnv 的时候,在NettyRpcEnv 内部,会将该 endpoint 的名称与其本省的映射关系,rpcEndpoint 与 rpcEndpointRef之间映射关系保存在 dispatcher 对应的成员变量中。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值