问题:在 main 方法完成执行且 Spark 上下文停止后,Kubernetes 上的 Spark 驱动程序进程不会终止。我正在尝试将当前在纱线上的 Spark 作业迁移到 Kubernetes。
JVM 进程的终止由 JVM 关闭序列启动,该序列通过以下两种方式之一触发:
为了识别导致问题的潜在线程,我打印了在 main 方法末尾运行的非守护线程列表。
Kubernetes 上的发现:main 方法末尾处 Kubernetes Spark 驱动程序上运行的非守护线程列表包括:
YARN 上的发现:YARN Spark 驱动程序中 main 方法末尾运行的非守护线程列表包括:
有趣的是,尽管这两种环境中都存在这些用户线程,YARN JVM 都会终止,而 Kubernetes 则不会。
在 YARN 上:当我们在 YARN 上以集群模式运行 Spark 时,Spark 使用 ApplicationMaster 类的实例启动驱动程序 JVM。然后,ApplicationMaster 在单独的线程中调用您的 Main 类(随后可能会创建其他线程)。但是,ApplicationMaster 仅等待主线程完成。这可以在 ApplicationMaster 类的以下代码片段中看到:
ugi.doAs(new PrivilegedExceptionAction[Unit]() { override def run(): Unit = System.exit(master.run()) })
这里,master.run() 调用主类并等待它完成,然后调用 System.exit,这会触发 JVM 关闭序列。
我找不到 Kubernetes 上发生的任何类似情况。
我想知道这是否是 YARN 上的预期行为? 我们应该在用户主类中执行 system.exit() 还是优雅地关闭所有用户线程?
哪里可以解决?有类似问题/