私が達成したいことが可能かどうかは確かです。私が知っていることは、エクゼキュータからシングルトンオブジェクトにアクセスして、コンストラクタが各エグゼキュータで一度だけ呼び出されていることを確認することです。このパターンはすでに実証済みで、私のコードベースで同様のユースケースに期待通りに機能します。エグゼキュータのSpark Object(シングルトン)シリアライズ
しかし、私が知りたいのは、オブジェクトをドライバで初期化した後に出荷できるかどうかです。このシナリオでは、 にアクセスすると、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
}
私も放送変数でこれを解決しようとしましたが、私はシングルトンオブジェクト内の放送変数にアクセスする方法がわからないと思います。
ありがとうございました。引数をオブジェクトに明示的に渡すと、argsを持つクラスになりますか? –
私はむしろメソッド呼び出しのパラメタを考えていました。オブジェクトの代わりにクラスを使うこともうまくいくはずです。 – user8925690