Spark调度系统——运行后端接口LauncherBackend

要介绍LauncherBackend,首先介绍下LaucherServer。当Spark应用程序没有在用户应用程序中运行,而是运行在单独的进程中时,用户可以在用户应用程序中使用LauncherServer与Spark应用程序通信。LauncherServer将提供Socket连接的服务端,与Spark应用程序中的Socket连接的客户端通信。LaucherServer的工作原理如下图:

TaskSchedulerImpl的底层依赖于LauncherBackend,而LaucherBackend依赖于BackendConnection跟LaucherServer进行通信

  • 1)调用LauncherBackend的connect方法创建BackendConnection,并且创建线程执行BackendConnection。构造BackendConnection的过程中,BackendConnection会和LaucherServer之间建立起Socket连接。BackendConnection(实现了java.lang.Runnable接口)将不断从Socket连接中读取LauncherServer发送的数据
  • 2)调用LauncherBackend的setAppId方法或SetState方法,通过向Socket连接向LancherServer发送SetAppId消息或SetState消息
  • 3)BackendConnection从Socket连接中读取到LauncherServer发送的Stop消息,然后调用LauncherBackend的fire

1 BackendConnection的实现

BackendConnection是LauncherBackend的内部组件,用于保持与LauncherServer的Socket连接,并通过此Socket连接收发消息。LauncherConnection提供了维护连接和收发消息的基本实现。

1.1 handle

handle是LauncherConnection提供的用于处理LauncherServer发送的消息的抽象方法

//org.apache.spark.launcher.LauncherConnection
protected abstract void handle(Message msg) throws IOException;

BackendConnection实现了LauncherConnection的handle方法,如下:

//org.apache.spark.launcher.LauncherBackend
override protected def handle(m: Message): Unit = m match {
  case _: Stop =>
    fireStopRequest()
  case _ =>
    throw new IllegalArgumentException(s"Unexpected message type: ${m.getClass().getName()}")
}

BackendConnection实现的handle方法只处理Stop这一咱消息。对于Stop消息,BackendConnection将调用外部类LauncherBackend的fireStopRequest方法停止Executor。

1.2 run

由于LauncherConnection实现了java.lang.Runnable接口,因此需要实现run方法。LauncherConnection的run方法用于从Socket客户端的输入流中读取LauncherServer发送的消息,并调用handle方法对消息进行处理。LauncerConnection的run方法同时也是一个模板方法。

//org.apache.spark.launcher.LauncherConnection
@Override
public void run() {
  try {
    ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
    while (!closed) {
      Message msg = (Message) in.readObject();
      handle(msg);
    }
  } catch (EOFException eof) {
    // Remote side has closed the connection, just cleanup.
    try {
      close();
    } catch (Exception unused) {
      // no-op.
    }
  } catch (Exception e) {
    if (!closed) {
      LOG.log(Level.WARNING, "Error in inbound message handling.", e);
      try {
        close();
      } catch (Exception unused) {
        // no-op.
      }
    }
  }
}

1.3 close

此方法用于关闭Socket客户端与LauncherServer的Socket服务端建立的连接,其实现代码清单如下:

//org.apache.spark.launcher.LauncherConnection
@Override
public void close() throws IOException {
  if (!closed) {
    synchronized (this) {
      if (!closed) {
        closed = true;
        socket.close();
      }
    }
  }
}

BackendConnection重写了LauncherConnection的close方法,其实现如下:

//org.apache.spark.launcher.LauncherBackend
override def close(): Unit = {
  try {
    super.close()
  } finally {
    onDisconnected()
    _isConnected = false
  }
}

BackendConnection重写的close方法首先调用了父类LauncherConnection的close方法关闭Socket连接,然后调用外部类LauncherBackend的onDisconnected方法。由于LauncherBackend的onDisconnected是个空方法,因此onDisconnected并不会有额外的效果。

2 LauncherBackend的实现

LauncherBackend是SchedulerBackend与LaucherServer通信的组件。其包含的属性有:

  • clientThread:读取与LaucherServer建立的Socket连接上的消息的线程
  • connection:即BackendConnection实例
  • lastState:LauncherBackend的最后一次状态。
  • _isConnected:clientThread是否与LauncherServer已经建立了Socket连接的状态

2.1 connect

用于和LauncherServer建立连接

//org.apache.spark.launcher.LauncherBackend
def connect(): Unit = {
  val port = sys.env.get(LauncherProtocol.ENV_LAUNCHER_PORT).map(_.toInt)
  val secret = sys.env.get(LauncherProtocol.ENV_LAUNCHER_SECRET)
  if (port != None && secret != None) {
    val s = new Socket(InetAddress.getLoopbackAddress(), port.get)
    connection = new BackendConnection(s)
    connection.send(new Hello(secret.get, SPARK_VERSION))
    clientThread = LauncherBackend.threadFactory.newThread(connection)
    clientThread.start()
    _isConnected = true
  }
}
  • 1)创建与LauncherServer的Socket服务端建立连接的Socket。
  • 2)通过此连接向LauncherServer发送Hello消息
  • 3)创建并启动一个执行BackendConnection的run方法的线程
  • 4)将_isConnected设置为true

2.2 setAppId

用于向LauncherServer发送SetAppId消息。SetAppId消息携带着应用程序的身份标识。

def setAppId(appId: String): Unit = {
  if (connection != null) {
    connection.send(new SetAppId(appId))
  }
}

2.3 setState

用于向LaucherServer发送SetState消息。SetState消息携带着LauncherBackend的最后一次状态。

def setState(state: SparkAppHandle.State): Unit = {
  if (connection != null && lastState != state) {
    connection.send(new SetState(state))
    lastState = state
  }
}

2.4 fireStopRequest

用于启动一个调用onStopRequest方法的线程

private def fireStopRequest(): Unit = {
  val thread = LauncherBackend.threadFactory.newThread(new Runnable() {
    override def run(): Unit = Utils.tryLogNonFatalError {
      onStopRequest()
    }
  })
  thread.start()
}

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值