【Spark 源码】1-Spark RPC

Spark RPC 概述

        Spark 是一个 通用的分布式计算系统,既然是分布式的,必然存在很多节点之间的通信,那么 Spark不同组件之间就会通过 RPC Remote Procedure Call )进行点对点通信。以下所有都是基于spark2.4.X版本进行分析学习的,该版本也是当前CDH 稳定版本
        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 数据
总结起来通信主要存在两个方面:
1. 汇集信息,例如 task 变化信息, executor 状态变化信息。
2. 传输数据, spark shuffle (也就是 reduce 从上游 map 的输出中汇集输入数据)阶段存在大量的数据传输。

RPC版本迭代

        早期版本是akka 和netty 共同组成的,Netty 做大数据传输,Akka 做组件之前的内部通信,在Spark2.0 Akka 完全被放弃了,全部都是依赖于Netty ,包括组件之前的通信、用户上传配置文件、Jar包、数据传输等。

SparkRPC 的原理

Akka工作原理

        在介绍新版本rpc 组成之前,先看下Akka 的大致工作原理,方便我们后续进行对比比较

  •  ActorSystem 管理通信角色 actor 的一个系统概念,在一个服务器节点中,只要存在一个这样的对象就可以,这个对象的作用,就是用来生成和管理所有的通信角色的生命周期
  • 通信角色 Actor,存在于一台服务器中的一个 ActorSystem 的内部,用来和其他节点的 actor 进行通信。每个 Actor 都有一个 MailBox,别的Actor 发送给它的消息都首先储存在 MailBox 中,通过这种方式可以实现异步通信。
  • Actor 要和另外一个 Actor 进行通信,则必须先获取对方 Actor ActorRef 对象,然后通过该对象发送消息即可。
  • 消息可以选择进行异步、同步、有反馈、无反馈的进行发送。

Sprak Netty 

        spark 基于 netty 新的 rpc 框架借鉴了 Akka 的中的设计,它是基于 Actor模型,各个组件可以认为是一个 个独立的实体,各个实体之间通过消息来进行通信。       
   
  • RpcEnv 类似于 ActorSystem,服务端和客户端都可以使用它来做通信。
  • RpcEndPoint 是一个可以相应请求的服务,类似于 Akka 中的 Actor 。其中有 receive 方法用来接收客户端发送过来的信息,也有 receiveAndReply 方法用来接收并应答,应答通过 RpcContext 回调。
  • RpcEndpointRef  类似于 Akka 中的 ActorRef ,是 RpcEndPoint 的引用,持有远程 RpcEndPoint 的地址名称等,提供了 send 方法和 ask 方法用于发送请求。

Spark RPC 类图

 源码解析

RpcEnv 

  • RpcEnvFactory负责创建

  • 负责RpcEndpoint的整个生命周期管理

  • 注册或者销毁Endpoint

  • 解析TCP层的数据包并反序列化对相应序列化后通过TPC传输到远端

  • 路由请求到指定的Endpoint

 核心方法

注册一个RPCEndpoint 到SparkRPC 中

/**
     * 
     * @param name RPC 名称
     * @param endpoint RPC通信实体 
     * @return  通信实体引用
     */
    def setupEndpoint(name: String, endpoint: RpcEndpoint): RpcEndpointRef

RpcEndpoint生命周期

onStart    作为初始化方法,在接受消息之前进行预处理

onStop.  在消息处理完毕后进行收尾操作 

 receive()为单次接收不进行回复,对应的是 RpcEndpointRef.send

 receiveAndReply 为接收消息,并进行相关回复,对应的是RpcEndpointRef.ask

 Dispatcher 消息路由

  • 调用Inbox的post方法将消息放入message
  • 将有消息的Inbox相关联的EndpointData放入receivers
  • MessageLoop每次循环先从receivers中获取EndpointData
  • 执行EndpointData中的Inbox的process方法对消息进行处理

 由上图代码看出是先从EndpointData找出对应的Inbox,然后对消息进行处理。

 InBox OutBox

对消息进行缓冲 存储

OutboxMessage 存储在OutBox 中,InboxMessage 存储在Inbox 中

客户端发送RPC时序图

 注:本文源码均为2.4.x 版本 即当前CDH 稳定运行版本!后续无特殊说明均为该版本

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值