我不确定我想实现的是否可能。我所知道的是,我正从一个执行器访问单例对象,以确保它的构造器在每个执行器上只被调用一次。这种模式已经在我的代码库中被证明和按照预期用于类似的用例。执行者上的Spark对象(单例)序列化
但是,我想知道的是,如果我可以在驱动程序初始化之后运送对象。在这种情况下, 访问ExecutorAccessedObject.y
时,理想情况下它不会调用println,而是返回值。这是一个高度简化的版本,实际上,我想打电话给驱动程序上的某个外部系统,因此在执行程序上访问时,它不会重新调用该外部系统。我确信@transient lazy val x
在执行者上被重新初始化,因为这将持有无法序列化的连接池。
object ExecutorAccessedObject extends Serializable {
@transient lazy val x: Int = {
println("Ok with initialzing this on the executor. I.E. database connection pool")
1
}
val y: Int = {
// call some external system to return a value.
// I do not want to call the external system from the executor
println(
"""
|Idealy, this would not be printed on the executor.
|return value 1 without re initializing
""")
1
}
println("The constructor will be initialized Once on each executor")
}
someRdd.mapPartitions { part =>
ExecutorAccessedObject
ExecutorAccessedObject.x // first time accessed should re-evaluate
ExecutorAccessedObject.y // idealy, never re-evaluate and return 1
part
}
我试图用广播变量解决这个问题,但我不确定如何访问单例对象内的广播变量。
谢谢你的回答。当你说明确地将参数传递给对象时,你的意思是使它成为一个带有参数的类? –
我宁愿考虑参数化方法调用。使用类而不是对象应该也可以。 – user8925690