Spark 内置的RPC框架前后共有两种架构,一个是在Spark2.0.0中被移除的Akka,一个则是借鉴了Akka 的 Actor 模型的Netty
一. Spark 内置 RPC 框架详解
在 Spark 中, 很多地方都涉及到网络通讯, 比如 Spark 各个组件间的消息互通, 用户文件与 Jar 包的上传, 节点间的 Shuffle 过程, Block 数据的复制与备份等.
- 在 Spark0.x.x 与 Spark1.x.x 版本中, 组件间的消息通信主要借助于 Akka.
- 在 Spark1.3 中引入了 Netty 通信框架. Akka要求message发送端和接收端有相同的版本, 所以为了避免 Akka 造成的版本问题,并给用户的应用更大灵活性,决定使用更通用的 RPC 实现,也就是现在的 Netty 来替代 Akka。
- Spark1.6 中 Akka 和 Netty 可以配置使用。Netty 完全实现了 Akka 在Spark 中的功能。
- 从Spark2.0.0, Akka 被移除.
- 1.
Actor
模型
- 2.
Netty
通信架构
Netty
借鉴了 Akka
的 Actor
模型
Spark通讯框架中各个组件(Client/Master/Worker
)可以认为是一个个独立的实体,各个实体之间通过消息来进行通信。
具体各个组件之间的关系图如下:
Endpoint(Client/Master/Worker)
有 1 个 InBox 和 N 个 OutBox(N>=1,N取决于当前 Endpoint 与多少其他的 Endpoint 进行通信,一个与其通讯的其他Endpoint 对应一个 OutBox),Endpoint 接收到的消息被写入 InBox,发送出去的消息写入 OutBox 并被发送到其他 Endpoint 的 InBox 中。
二. Spark Netty
通信架构
Netty 官网: https://netty.io/
2.1 Netty
的详细架构图
-
RpcEndpoint
:RPC 端点。
Spark 针对每个节点(Client/Master/Worker)都称之为一个 RpcEndpoint ,且都实现 RpcEndpoint接口,内部根据不同端点的需求,设计不同的消息和不同的业务处理,如果需要发送(询问)则内部调用 Dispatcher 的对应方法;
说明:
- RpcEndpoint 是用来接收消息.
- 发送消息的使用RpcEndpointRef
- RpcEndpointRef的具体实现类是: NettyRpcEndpointRef
- 2.
RpcEnv
: Rpc 上下文(Rpc 环境)
每个RpcEndpoint运行时依赖的上下文环境称为 RpcEnv
- 3.
Dispatcher
:消息分发器
RPC 端点需要发送消息或者从远程 RPC 端点接收到的消息,分发至对应的指令收件箱/发件箱。
- 如果指令接收方是自己则存入收件箱
- 如果指令接收方不是自己则放入发件箱
// class NettyRpcEnv
private[netty] def send(message: RequestMessage): Unit = {
// 获取接收者地址信息
val remoteAddr = message.receiver.address
if (remoteAddr == address) {
// Message to a local RPC endpoint.
// 把消息发送到本地的 RPC 端点 (发送到收件箱)
try {
dispatcher.postOneWayMessage(message)
} catch {
case e: RpcEnvStoppedException => logWarning(e.getMessage)
}
} else {
// Message to a remote RPC endpoint.
// 把消息发送到远程的 RPC 端点. (发送到发件箱)
postToOutbox(message.receiver, OneWayOutboxMessage(serialize(message)))
}
}
- 4.
Inbox
:指令消息收件箱。
一个本地 RpcEndpoint 对应一个收件箱
- 5.
RpcEndpointRef
:RpcEndpointRef 是对远程 RpcEndpoint 的一个引用。
当我们需要向一个具体的 RpcEndpoint 发送消息时,一般我们需要获取到该RpcEndpoint 的引用,然后通过该引用发送消息。
- 6.
OutBox
:指令消息发件箱。
对于当前 RpcEndpoint 来说,一个目标 RpcEndpoint 对应一个当前的发件箱,如果向多个目标 RpcEndpoint 发送信息,则有当前会有多个 OutBox。当消息放入 Outbox 后,紧接着通过 TransportClient 将消息发送出去。消息放入发件箱以及发送过程是在同一个线程中进行;
- 7.
RpcAddress
表示远程的RpcEndpointRef的地址,Host Port。
- 8.
TransportClient
:Netty通信客户端
一个 OutBox 对应一个 TransportClient,TransportClient 不断轮询OutBox,根据 OutBox 消息的 receiver 信息,请求对应的远程 TransportServer;
- 9. TransportServer:Netty 通信服务端
一个 RpcEndpoint 对应一个 TransportServer,接受远程消息后调用 Dispatcher 分发消息至自己的收件箱,或者对应的发件箱;
2.2 高层俯视图
本次的分享就到这里了