1.这个类主要作用是接受消息然后调用listener监听 * * ----------------------- ----------------------- * | User App | spark-submit | Spark App | * | | -------------------> | | * | ------------| |------------- | * | | | hello | | | * | | L. Server |<----------------------| L. Backend | | * | | | | | | * | ------------- ----------------------- * | | | ^ * | v | | * | -------------| | * | | | <per-app channel> | * | | App Handle |<------------------------------ * | | | * -----------------------
1.LauncherServer主要有两个作用:一个作用是可以定时关闭client连接的线程,一个作用是创建ChildProcAppHandle.
2.LauncherConnection 这个类是抽离出来的一个连接类,重要方法handle(Message meg) 3.LauncherBackend 主要用来与服务端通信class LauncherServer implements Closeable { private static final Logger LOG = Logger.getLogger(LauncherServer.class.getName()); private static final String THREAD_NAME_FMT = "LauncherServer-%d"; //连接超时 private static final long DEFAULT_CONNECT_TIMEOUT = 10000L; //与子进程通信的密钥 private static final SecureRandom RND = new SecureRandom(); private static volatile LauncherServer serverInstance; static synchronized ChildProcAppHandle newAppHandle() throws IOException { //初始化LauncherServer LauncherServer server = serverInstance != null ? serverInstance : new LauncherServer(); //标记数量 server.ref(); //该对象持有这个server serverInstance = server; //创建密钥 String secret = server.createSecret(); //已经有了重新创建 while (server.pending.containsKey(secret)) { secret = server.createSecret(); } //返回server的AppHandle return server.newAppHandle(secret); } static LauncherServer getServerInstance() { return serverInstance; } private final AtomicLong refCount; private final AtomicLong threadIds; //标记服务器有的Handle private final ConcurrentMap<String, ChildProcAppHandle> pending; //连接的客户端 private final List<ServerConnection> clients; private final ServerSocket server; private final Thread serverThread; private final ThreadFactory factory; private final Timer timeoutTimer; private volatile boolean running; private LauncherServer() throws IOException { //初始化个数 this.refCount = new AtomicLong(0); //初始化ServerSocket ServerSocket server = new ServerSocket(); try { //端口复用 server.setReuseAddress(true); server.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); this.clients = new ArrayList<>(); this.threadIds = new AtomicLong(); this.factory = new NamedThreadFactory(THREAD_NAME_FMT); this.pending = new ConcurrentHashMap<>(); //Timer类【实际上是一个线程套一个无限循环】的定时器。 this.timeoutTimer = new Timer("LauncherServer-TimeoutTimer", true); this.server = server; this.running = true; //服务器接受连接 this.serverThread = factory.newThread(new Runnable() { @Override public void run() { acceptConnections(); } }); //服务器启动 serverThread.start(); } catch (IOException ioe) { close(); throw ioe; } catch (Exception e) { close(); throw new IOException(e); } } ChildProcAppHandle newAppHandle(String secret) { //注册child handle ChildProcAppHandle handle = new ChildProcAppHandle(secret, this); //重复的key不会覆盖 ChildProcAppHandle existing = pending.putIfAbsent(secret, handle); CommandBuilderUtils.checkState(existing == null, "Multiple handles with the same secret."); return handle; } //以下主要是连接关闭的清除操作 @Override public void close() throws IOException { synchronized (this) {//对象锁 if (running) { running = false; timeoutTimer.cancel();//清除执行队列 server.close(); synchronized (clients) { List<ServerConnection> copy = new ArrayList<>(clients); clients.clear(); for (ServerConnection client : copy) { client.close(); } } } } if (serverThread != null) { try { serverThread.join(); } catch (InterruptedException ie) { // no-op } } } //累加计数 void ref() { refCount.incrementAndGet(); } void unref() { synchronized(LauncherServer.class) { if (refCount.decrementAndGet() == 0) { try { close(); } catch (IOException ioe) { // no-op. } finally { serverInstance = null; } } } } //服务器端口 int getPort() { return server.getLocalPort(); } void unregister(ChildProcAppHandle handle) { pending.remove(handle.getSecret()); unref(); } private void acceptConnections() { try { while (running) { //服务器等待 final Socket client = server.accept(); //定义一个线程关闭的操作 TimerTask timeout = new TimerTask() { @Override public void run() { LOG.warning("Timed out waiting for hello message from client."); try { client.close(); } catch (IOException ioe) { // no-op. } } }; //涉及到了LauncherConnection初始化了输出对象 ServerConnection clientConnection = new ServerConnection(client, timeout);
Thread clientThread = factory.newThread(clientConnection); synchronized (timeout) { clientThread.start(); synchronized (clients) { //建立连接并通信,添加客户端到列表中 clients.add(clientConnection); } //得到超时时间 spark.launcher.childConectionTimeout 默认10000L long timeoutMs = getConnectionTimeout(); // 0 is used for testing to avoid issues with clock resolution / thread scheduling, // and force an immediate timeout. if (timeoutMs > 0) { //到一定时间就关掉连接 timeoutTimer.schedule(timeout, getConnectionTimeout()); } else { timeout.run(); } } } } catch (IOException ioe) { if (running) { LOG.log(Level.SEVERE, "Error in accept loop.", ioe); } } } //超时配置 private long getConnectionTimeout() { String value = SparkLauncher.launcherConfig.get(SparkLauncher.CHILD_CONNECTION_TIMEOUT); return (value != null) ? Long.parseLong(value) : DEFAULT_CONNECT_TIMEOUT; } //加密算法 private String createSecret() { byte[] secret = new byte[128]; RND.nextBytes(secret); StringBuilder sb = new StringBuilder(); for (byte b : secret) { int ival = b >= 0 ? b : Byte.MAX_VALUE - b; if (ival < 0x10) { sb.append("0"); } sb.append(Integer.toHexString(ival)); } return sb.toString(); } private class ServerConnection extends LauncherConnection { private TimerTask timeout; private ChildProcAppHandle handle; ServerConnection(Socket socket, TimerTask timeout) throws IOException { super(socket); this.timeout = timeout; } //多种消息类型读取识别,并且会调用用户提供的listener @Override protected void handle(Message msg) throws IOException { try { if (msg instanceof Hello) { timeout.cancel(); timeout = null; Hello hello = (Hello) msg; ChildProcAppHandle handle = pending.remove(hello.secret); if (handle != null) { handle.setConnection(this); handle.setState(SparkAppHandle.State.CONNECTED); this.handle = handle; } else { throw new IllegalArgumentException("Received Hello for unknown client."); } } else { if (handle == null) { throw new IllegalArgumentException("Expected hello, got: " + msg != null ? msg.getClass().getName() : null); } if (msg instanceof SetAppId) { SetAppId set = (SetAppId) msg; handle.setAppId(set.appId); } else if (msg instanceof SetState) { handle.setState(((SetState)msg).state); } else { throw new IllegalArgumentException("Invalid message: " + msg != null ? msg.getClass().getName() : null); } } } catch (Exception e) { LOG.log(Level.INFO, "Error handling message from client.", e); if (timeout != null) { timeout.cancel(); } close(); } finally { timeoutTimer.purge(); } } LauncherBackend类:
static final String ENV_LAUNCHER_PORT = "_SPARK_LAUNCHER_PORT"; static final String ENV_LAUNCHER_SECRET = "_SPARK_LAUNCHER_SECRET"; 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) //还是通过它建立的链接LauncherConnection connection = new BackendConnection(s) //网络流的写 connection.send(new Hello(secret.get, SPARK_VERSION)) //客户端连接 clientThread = LauncherBackend.threadFactory.newThread(connection) clientThread.start() _isConnected = true }
形成了客户端发送的消息,服务端达到一定时间就会关闭连接。