SPARK 的通信架构 - Akka Actor 比较,如下图所示:

image.png

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

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

6.2.1 通信组件概览

对源码分析,对于设计思路理解如下:

image.png

概念:

  • RpcEndpointRPC 端点 。Spark 针对于每个节点(Client/Master/Worker)都称之一个 RPC 端点,且都实现 RpcEndpoint 接口,内部根据不同端点的需求,设计不同的消息和不同的业务处理,如果需要发送(询问)则调用 Dispatcher。 一个端点就有一个 inbox,根据你通信的其他端点的数目,就有多个 Outbox
  • RpcEnvRPC 上下文环境。每个 Rpc 端点运行时依赖的上下文环境称之为 RpcEnv
  • Dispatcher消息分发器。针对于 RPC 端点需要发送消息或者从远程 RPC 接收到的消息,分发至对应的指令收件箱/发件箱。如果指令接收方是自己存入收件箱,如果指令接收方为非自身端点,则放入发件箱。
  • Inbox指令消息收件箱。一个本地端点对应一个收件箱,Dispatcher 在每次向 Inbox 存入消息时,都将对应 EndpointData 加入内部待 Receiver Queue 中,另外 Dispatcher 创建时会启动一个单独线程进行轮询 Receiver Queue,进行收件箱消息消费。
  • OutBox指令消息发件箱。一个远程端点对应一个发件箱,当消息放入 Outbox 后,紧接着将消息通过 TransportClient 发送出去。消息放入发件箱以及发送过程是在同一个线程中进行,这样做的主要原因是远程消息分为 RpcOutboxMessage, OneWayOutboxMessage 两种消息,而针对于需要应答的消息直接发送且需要得到结果进行处理。
  • TransportClientNetty 通信客户端。根据 OutBox 消息的 receiver 信息,请求对应远程 TransportServer。
  • TransportServerNetty 通信服务端。一个 RPC 端点一个 TransportServer,接受远程消息后调用 Dispatcher 分发消息至对应收发件箱。

注意:

  • TransportClient 与 TransportServer 通信虚线表示两个 RpcEnv 之间的通信,图示没有单独表达式。
  • 一个 Outbox 一个 TransportClient,图示没有单独表达式。
  • 一个 RpcEnv 中存在两个 RpcEndpoint,一个代表本身启动的 RPC 端点,另外一个为 RpcEndpointVerifier

Spark 的通信架构 – 高层视图:

image.png

Spark 的通信架构 – 类图:

image.png

6.2.2 Endpoint 启动过程

启动的流程如下:

image.png

Endpoint 启动后,默认会向 Inbox 中添加 OnStart 消息,不同的端点(Master/Worker/Client)消费 OnStart 指令时,进行相关端点的启动额外处理。Endpoint 启动时,会默认启动 TransportServer,且启动结束后会进行一次同步测试 rpc** 可用性(askSync-BoundPortsRequest)。

Dispatcher 作为一个分发器,内部存放了 Inbox、Outbox 等相关句柄和存放了相关处理状态数据,结构大致如下:

image.png

6.2.3 Endpoint Send&Ask 流程

Endpoint 的消息发送与请求流程,如下:

image.png

Endpoint 根据业务需要存入两个维度的消息组合send/ask 某个消息,receiver 是自身与非自身:

  • OneWayMessage: send + 自身, 直接存入收件箱
  • OneWayOutboxMessage:send + 非自身,存入发件箱并直接发送
  • RpcMessage:ask + 自身,直接存入收件箱,另外还需要存入 LocalNettyRpcCallContext,需要回调后再返回。
  • RpcOutboxMessage: ask + 非自身,存入发件箱并直接发送,需要回调后再返回。

2.4 Endpoint Receive 流程

Endpoint 的消息的接收,流程如下:

image.png

上图 ServerBootstrap 为 Netty 启动服务,SocketChanel 为 Netty 数据通道。 上述包含 TransportSever 启动与消息接收两个流程。

2.5 Endpoint Inbox 处理流程

**
Spark 在 Endpoint 的设计上核心设计即为 Inbox 与 Outbox,其中 Inbox 核心要点为:

  • 内部的处理流程拆分为多个消息指令(InboxMessage)存放入 Inbox
  • Dispatcher 启动最后,会启动一个名为【dispatcher-event-loop】的线程扫描 Inbox 待处理 InboxMessage,并调用 Endpoint 根据 InboxMessage 类型做相应处理。
  • Dispatcher 启动最后,默认会向 Inbox 存入 OnStart 类型的 InboxMessage,Endpoint 在根据 OnStart 指令做相关的额外启动工作,三端启动后所有的工作都是对 OnStart 指令处理衍生出来的,因此可以说 OnStart 指令是相互通信的源头

消息指令类型大致如下三类

  • OnStart/OnStop
  • RpcMessage/OneWayMessage
  • RemoteProcessDisconnected/RemoteProcessConnected/RemoteProcessConnectionError

image.png

2.6 Endpoint 画像

image.png