Spark RPC实现原理分析

Spark RPC模块架构图

Spark RPC是按照MailBox的设计思路来实现的,为了能够更直观地表达RPC的设计,我们先从RPC架构图来看,如下图所示:

Spark RPC体系结构图

该图主要描述了从客户端向服务器端发送远程消息在服务器端发送本地消息的过程,该过程中显示了消息的流动及格式转换,还有各个组件之间的分工协作。

组件介绍

核心组件

Spark RPC通信主要有RpcEnvRpcEndpointRpcEndpointRef这三个核心类。

  1. RpcEndpoint

    该类定义了RPC通信过程中的服务器端对象,除了具有管理一组RpcEndpoint生命周期的操作(constructor -> onStart -> receive* -> onStop),并给出了通信过程中RpcEndpoint所具有的基于事件驱动的行为(连接、断开、网络异常),实际上对于Spark框架来说主要是接收消息并处理

    private[spark] trait RpcEndpoint {
         
    
       /**
         * 当前RpcEndpoint所注册的[[RpcEnv]]
         */
       val rpcEnv: RpcEnv
    
       /**
         * 当前[[RpcEndpoint]]的代理,当`onStart`方法被调用时`self`生效,当`onStop`被调用时,`self`变成null。
         * 注意:在`onStart`方法被调用之前,[[RpcEndpoint]]对象还未进行注册,所以就没有有效的[[RpcEndpointRef]]。
         */
       final def self: RpcEndpointRef = {
           require(rpcEnv != null, "rpcEnv has not been initialized")
           rpcEnv.endpointRef(this)
       }
    
       /**
         * 用于处理从`RpcEndpointRef.send` 或 `RpcCallContext.reply`接收到的消息。
         * 如果接收到一个不匹配的消息,将会抛出SparkException异常,并发送给`onError`
         *
         * 通过上面的receive方法,接收由RpcEndpointRef.send方法发送的消息,
         * 该类消息不需要进行响应消息(Reply),而只是在RpcEndpoint端进行处理。
         */
       def receive: PartialFunction[Any, Unit] = {
           case _ => throw new SparkException(self + " does not implement 'receive'")
       }
    
       /**
         * 处理来自`RpcEndpointRef.ask`的消息,RpcEndpoint端处理完消息后,需要给调用RpcEndpointRef.ask的通信端返回响应消息。
         */
       def receiveAndReply(context: RpcCallContext): PartialFunction[Any, Unit] = {
           case _ => context.sendFailure(new SparkException(self + " won't reply anything"))
       }
    
       /**
         * 在处理消息期间出现异常的话将被调用
         */
       def onError(cause: Throwable): Unit = {
           // By default, throw e and let RpcEnv handle it
           throw cause
       }
    
       /**
         * 当有远端连接到当前服务器时会被调用
         */
       def onConnected(remoteAddress: RpcAddress): Unit = {
           // By default, do nothing.
       }
    
       /**
         * 当远端与当前服务器断开时,该方法会被调用
         */
       def onDisconnected(remoteAddress: RpcAddress): Unit = {
           // By default, do nothing.
       }
    
       /**
         * 当前节点与远端之间的连接发生错误时,该方法将会被调用
         */
       def onNetworkError(cause: Throwable, remoteAddress: RpcAddress): Unit = {
           // By default, do nothing.
       }
    
       /**
         * 在 [[RpcEndpoint]] 开始处理消息之前被调用
         */
       def onStart(): Unit = {
           // By default, do nothing.
       }
    
       /**
         * 当[[RpcEndpoint]]正在停止时,该方法将会被调用。
         * `self`将会在该方法中被置位null,因此你不能使用它来发送消息。
         */
       def onStop(): Unit = {
           // By default, do nothing.
       }
    
       /**
         * A convenient method to stop [[RpcEndpoint]].
         */
       final def stop(): Unit = {
           val _self = self
           if (_self != null) {
               rpcEnv.stop(_self)
           }
       }
    }
  2. RpcEndpointRef

    RpcEndpointRef是一个对RpcEndpoint的远程引用对象,通过它可以向远程的RpcEndpoint端发送消息以进行通信。RpcEndpointRef特质的定义,代码如下所示:

    private[spark] abstract class RpcEndpointRef(conf: SparkConf) extends Serializable with Logging {
         
    
       private[this] val maxRetries = RpcUtils.numRetries(conf)
       private[this] val retryWaitMs = RpcUtils.retryWaitMs(conf)
       private[this] val defaultAskTimeout = RpcUtils.askRpcTimeout(conf)
    
       /**
         * 返回[RpcEndpointRef]]的引用的远端服务器地址
         */
       def address: RpcAddress
    
       def name: String
    
       /**
         * 发送一条单向的异步消息,并且发送消息后不等待响应,亦即Send-and-forget。
         */
       def send(message: Any): Unit
    
       /**
         * 发送消息给相关的[[RpcEndpoint.receiveAndReply]],并且返回一个 Future,能够在timeout时间内接收回复。
         * 该方法只会发送一次消息,失败后不重试。
         * 而ask方法发送消息后需要等待通信对端给予响应
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值