Scala spark停止时如何清理其他资源

Scala spark停止时如何清理其他资源,scala,apache-spark,akka,Scala,Apache Spark,Akka,在我的spark应用程序中,有一个对象ResourceFactory,其中包含一个akkaActorSystem,用于提供资源客户端。因此,当我运行这个spark应用程序时,每个工作节点都将创建一个ActorSystem。问题是,当spark应用程序完成其工作并关闭时。ActorSystem在每个工作节点上仍然保持活动状态,并防止整个应用程序终止,它只是挂起 有没有办法将一些侦听器注册到SparkContext,这样当sc关闭时,每个工作节点上的ActorSystem都会收到关闭自己的通知 更

在我的spark应用程序中,有一个
对象ResourceFactory
,其中包含一个akka
ActorSystem
,用于提供资源客户端。因此,当我运行这个spark应用程序时,每个工作节点都将创建一个
ActorSystem
。问题是,当spark应用程序完成其工作并关闭时。
ActorSystem
在每个工作节点上仍然保持活动状态,并防止整个应用程序终止,它只是挂起

有没有办法将一些侦听器注册到
SparkContext
,这样当
sc
关闭时,每个工作节点上的
ActorSystem
都会收到关闭自己的通知


更新:

以下是简化的框架:

有一个
资源工厂
,它是一个
对象
,它包含一个
参与者系统
。它还提供了一个
fetchData
方法

object ResourceFactory{
  val actorSystem = ActorSystem("resource-akka-system")
  def fetchData(): SomeData = ...
}
然后,有一个
用户定义的RDD
类,在它的
计算
方法中,它需要从
资源工厂
获取数据

class MyRDD extends RDD[SomeClass] {
  override def compute(...) {
    ...
    ResourceFactory.fetchData()
    ...
    someIterator
  }
}
因此,在每个节点上都会有一个名为“resource akka system”的
ActorSystem
,分布在这些工作节点上的
MyRDD
实例可以从“resource akka system”获取数据

问题是,当
SparkContext
关闭时,不需要那些“资源akka系统”,但我不知道如何通知
ResourceFactory
SparkContext
关闭时关闭“资源akka系统”。所以现在,“资源akka系统”在每个工作节点上保持活动状态,并阻止整个程序退出


更新2:

通过更多的实验,我发现在本地模式下程序被挂起,但在
纱线簇
模式下,程序将成功退出。这可能是因为当
sc
关闭时,
warn
将终止工作节点上的线程


更新3:

为了检查每个节点是否都包含一个
ActorSystem
,我将代码更改如下(下面是真实的框架,因为我添加了另一个类定义):

在添加了那些
println
s之后,我在spark on Thread cluster模式下运行代码。我发现在司机身上有以下指纹:

creating my rdd
creating resource factory
creating my rdd
...
creating rdd iterator
creating resource factory
在一些工人身上,我有以下照片:

creating my rdd
creating resource factory
creating my rdd
...
creating rdd iterator
creating resource factory
而一些工人,它什么也不打印(而且他们都没有被分配任何任务)

基于上述情况,我认为
对象
是在驱动程序中急切地初始化的,因为它在驱动程序上打印
创建资源工厂
,即使没有任何东西引用它,而
对象
在worker中被惰性地初始化,因为它在打印
创建rdd迭代器
后打印
创建资源工厂
,因为资源工厂被第一个创建的rdd迭代器惰性地引用

我发现在我的用例中,
MyRDD
类只在驱动程序中创建


我不太确定在驱动程序和工作程序上初始化
对象
的惰性,这是我的猜测,因为可能是程序的其他部分造成的。但我认为,在必要时,每个工作节点上都有一个参与者系统应该是正确的。

我认为没有办法进入每个
工作节点的生命周期

此外,我对您的实施有一些疑问:

  • 如果您有一个包含
    val
    对象,它是从worker上运行的函数中使用的,我的理解是这个
    val
    被序列化并广播给worker。您能否确认每个工人都有一个ActorSystem运行

  • 若并没有显式地等待Actor系统的终止,它通常会立即终止。您是在调用类似于
    系统的东西。等待终止
    还是在
    系统上阻塞。何时终止



  • 无论如何,还有另一种方法,可以关闭远程工作者上的actor系统:

  • 使您的ActorSystem位于akka集群的每个节点上。如何以编程方式实现这一点
  • 将“协调”参与者在驱动程序节点上的地址(您的
    sc
    所在位置)广播给每个工作人员。简单地说,只需将
    val
    与该地址关联即可
  • 在每个工作人员上启动akka系统时,使用该“协调”参与者地址注册该特定参与者系统(向协调参与者发送相应消息)
  • 协调参与者跟踪所有注册的“工人”参与者
  • 当您的计算完成并且希望关闭每个工作程序上的Akka系统时,从驱动程序节点上的协调参与者向所有注册的参与者发送消息
  • 收到“关机”消息时,工人Akka系统关机

  • 对于第一个问题,我需要几天后确认每个worker节点都有一个ActorSystem。现在从理论上讲,我认为在启动spark时,所有字节码都将被发送到每台机器,因此当我在RDD代码中引用一个对象时,它将引用本地发送和类加载的对象实例。基于此,我认为每个节点都有一个ActorSystem。如果是错误的,那么我认为我误解了spark,请指出并纠正我。对于第二个问题,请参见问题中的更新2,我认为这是相关的。回到问题上来,我不会调用任何类似于
    system.aWritermination
    的东西。我认为Actor系统不会终止,除非我调用类似于
    System.shutdown的东西。也许我又错了@宇宙人, 根据编程指南,您的代码被发送到驱动程序节点,然后驱动程序节点将字节码和序列化的“封闭范围”一起分发给工作人员。检查该部分。但我不能100%确定你的情况会怎样