Spark最新2.x源码二-----------SparkRPC架构-RPC发展史--RpcEndpoint---RpcEnv---RpcEndpointRef

版权声明:本文为博主原创文章,未经博主允许不得转载!!

欢迎访问:https://blog.csdn.net/qq_21439395/article/details/82817538

交流QQ: 824203453

  1. Spark Rpc 架构
    1. 演变历程简述:

Actor中有3个重要概念,ActorSystemActorActorRef 

spark1.4规范了rpc的接口,该规范根据akka的actor抽象出三个重要的接口(Trait 特质 和抽象类),并且和actor中class对应关系如下 :

RpcEnv => ActorSystem
RpcEndpoint => Actor 
RpcEndpointRef => ActorRef 

在Akka中,rpc的通信的两端称之为Actor

1.4版本的RPC接口规范之后,rpc通信的两端称之为endpoint。每一个endpoint都要实现RpcEndpoint特质。

每一个endpoint,都要由一个管理者创建,这个管理者就是RpcEnv。

同Actor一样,一个Jvm中只有一个管理者,但可以有多个endpoint。

想要进行通信,就必须拿到对方endpoint的引用,也就是RpcEndpointRef。

 

spark1.6版本中,底层的通信框架引入了新的netty,保留了akka

 

 

spark2.0版本中,移除了akka

      1. Rpc架构

SparkRPC架构的核心对象:

 

RPC 全家福:

 

      1. RpcEndpoint

RpcEndpoint功能同Actor,用于rpc通信的实体,通信并处理消息。

 

一个RpcEndpoint的生命周期方法主要有: 

onStart -> receive / receiveAndReply -> onStop

其他的方法主要是处理连接建立断开和错误等事件。

 

/**
 * Invoked before
[[RpcEndpoint]] starts to handle any message.
 */

def onStart(): Unit = {
 
// By default, do nothing.
}

/**
 * Process messages from
`RpcEndpointRef.send` or `RpcCallContext.reply`. If receiving a
 * unmatched message,
`SparkException` will be thrown and sent to `onError`.
 */

def receive: PartialFunction[Any, Unit] = {
 
case _ => throw new SparkException(self + " does not implement 'receive'")
}

/**
 * Process messages from
`RpcEndpointRef.ask`. If receiving a unmatched message,
 *
`SparkException` will be thrown and sent to `onError`.
 */

def receiveAndReply(context: RpcCallContext): PartialFunction[Any, Unit] = {
 
case _ => context.sendFailure(new SparkException(self + " won't reply anything"))
}

 

receivereceiveAndReply方法用于处理接收的消息,区别是后者处理完消息后会返回消息给发送者。receive方法处理完接收的消息,不给任何回复。

receive方法会被执行多次。

onStart方法,主要是在endpoint初始化之前的业务逻辑,也就是说在receive接收消息之前的业务逻辑。

onStart仅仅会被调用一次。

RpcEndpoint的特质继承关系:

Spark部署模式:Standalone集群。

Spark中的rpc通信主要有:

  1. Master ,集群管理者,接收客户端任务请求,管理worker
  2. Worker,向master发送心跳,管理executor
  3. StandaloneAppClient(拥有用于通信的内部类ClientEndpoint),ScheduleBackend持有它(standalone模式下,实例化为CoarseGrainedSchedulerBackend),在standalone部署模式下,driver通过它来与master通信
  4. DriverEndpoint,ScheduleBackend(standalone模式下,实例化为CoarseGrainedSchedulerBackend)用来与executor通信,收集executor信息,收集task变化信息
  5. CoarseGrainedExecutorBackend,每一个executor对应一个,和driver通信运行或取消任务等
  6. MapoutTracker,MapoutTracker有两个实现类:MapoutTrackerMaster和MapoutTrackerWorker。前者运行在Driver端,后者运行在每一个executor上,两者通信用来保存ShuffleMapTask的map输出数据信息。MapoutTrackerMaster持有MapoutTrackerMasterEndpoint接收信息,MapoutTrackerWorker持有EndpointRef汇报map out输出信息
  7. BlockManager,BlockManager负责spark运行期间的数据信息的收集以及存与取,BlockManager运行在Driver和每一个executor上,BlockManager持有BlockManagerMaster,在Driver上BlockManagerMaster持有BlockManagerMasterEndpoint,executor上持有EndpointRef,executor调用blockmanager汇报信息,实际上是通过endpointref汇集到driver上。

standaloneAppClient$ClientEndpoint ,driver通过这个和Master 进行通信

DriverEndpoint,driver通过这个和 executor进行通信。

 

      1. RpcEnv

RpcEndpoint是由RpcEnv来创建的。

RpcEnv是一个抽象类,在spark2.x版本中,使用的具体的实现类是NettyRpcEnv。

 

 

 

private[spark] object RpcEnv {
 
def create(
      name:
String,
      host:
String,
      port: Int,
      conf: SparkConf,
      securityManager: SecurityManager,
      clientMode: Boolean =
false): RpcEnv = {
    create(name, host, host, port, conf, securityManager, clientMode)
  }

 
def create(
      name:
String,
      bindAddress:
String,
      advertiseAddress:
String,
      port: Int,
      conf: SparkConf,
      securityManager: SecurityManager,
      clientMode: Boolean): RpcEnv = {
   
// 这个RpcEnvConfig 就类似于actorConfigFactory 获取config配置
   
val config = RpcEnvConfig(conf, name, bindAddress, advertiseAddress, port, securityManager,
      clientMode)
   
// 根据配置启动 RpcEnv
   
new NettyRpcEnvFactory().create(config)
  }
}

 

在object RpcEnv中,重要的功能是创建一个RpcEnv的实例,这个实例就是用于管理endpoint。

具体的一个endpoint(Worker)实例中的使用:

val rpcEnv = RpcEnv.create(SYSTEM_NAME, host, port, conf, securityMgr)

 

 

* An RPC environment. [[RpcEndpoint]]s need to register itself with a name to [[RpcEnv]] to
* receives messages. Then
[[RpcEnv]] will process messages sent from [[RpcEndpointRef]] or remote
* nodes, and deliver them to corresponding
[[RpcEndpoint]]s.

 

翻译一下:

RpcEnv 是一个RPC 环境。 RpcEndpoint需要使用RpcEnv的名称来注册自己,以接收消息。RpcEnv将处理从RpcEndpointRef或远程节点发送的消息,并将它们传递到相应的RpcEndpoint

 

private[spark] abstract class RpcEnv(conf: SparkConf) {

 

在抽象类 RpcEnv中,有一个重要且常用的方法setupEndpoint方法。该方法就是利用上述创建的RpcEnv实例,来初始化(注册)一个Endpoint,并返回该endpoint的RpcEndpointRef(俗称代理对象)。

必须拿到某一个Endpoint的代理对象才能向该endpoint发送消息。

/**
 * Register a
[[RpcEndpoint]] with a name and return its [[RpcEndpointRef]]. [[RpcEnv]] does not
 * guarantee thread-safety.
 */

def setupEndpoint(name: String, endpoint: RpcEndpoint): RpcEndpointRef

 

提供了一个setupEndpointRef 来获取到指定endpoint的引用对象。

/**
 * Retrieve the
[[RpcEndpointRef]] represented by `address` and `endpointName`.
 * This is a blocking action.
 */

def setupEndpointRef(address: RpcAddress, endpointName: String): RpcEndpointRef = {
  setupEndpointRefByURI(RpcEndpointAddress(address, endpointName).
toString)
}

 

 

一个具体的endpoint(worker)的实例化:

rpcEnv.setupEndpoint(ENDPOINT_NAME, new Worker(rpcEnv, webUiPort, cores, memory,
  masterAddresses,
ENDPOINT_NAME, workDir, conf, securityMgr))

 

  1. 5 RpcEndpointRef

RpcEndpointRef是RpcEndpoint的一个引用,简称代理。RpcEndpointRef是线程安全的。

要想向一个RpcEndpoint发送消息,必须先持有其Ref代理,通过该代理才能发送消息。

/**
 * A reference for a remote
[[RpcEndpoint]]. [[RpcEndpointRef]] is thread-safe.
 */

private[spark] abstract class RpcEndpointRef(conf: SparkConf)

 

RpcEndpointRef 抽象类的结构:

 

常用的发送消息的方法是send,ask,askSync。

/**
 * Sends a one-way asynchronous message. Fire-and-forget semantics.
 */

def send(message: Any): Unit

def ask[T: ClassTag](message: Any, timeout: RpcTimeout): Future[T]

 

def askSync[T: ClassTag](message: Any, timeout: RpcTimeout): T = {
 
val future = ask[T](message, timeout)
  timeout.awaitResult(future)
}

 

send发送的消息,没有返回值,用receive接收即可。

ask和askSync,发送的消息有返回值,用receiveAndReply来接收。

实例: worker获取到master的ref引用对象,然后发送注册消息。

masterEndpoint.send(RegisterWorker(
 
// 生成workerId,格式为:格式:worker-时间-主机名-端口
 
workerId,host, port, self,  cores,  memory,  workerWebUiUrl,  masterEndpoint.address))

版权声明:本文为博主原创文章,未经博主允许不得转载!!

欢迎访问:https://blog.csdn.net/qq_21439395/article/details/82817538

交流QQ: 824203453

猜你喜欢

转载自blog.csdn.net/qq_21439395/article/details/82817538