我在Spark Streaming应用程序中广播一个值。但我不知道如何在与播放它的类不同的类中访问该变量。
我的代码如下:
object AppMain{
def main(args: Array[String]){
//...
val broadcastA = sc.broadcast(a)
//..
lines.foreachRDD(rdd => {
val obj = AppObject1
rdd.filter(p => obj.apply(p))
rdd.count
}
}
object AppObject1: Boolean{
def apply(str: String){
AnotherObject.process(str)
}
}
object AnotherObject{
// I want to use broadcast variable in this object
val B = broadcastA.Value // compilation error here
def process(): Boolean{
//need to use B inside this method
}
}
在这种情况下,有人可以建议如何访问广播变量吗?
答案 0 :(得分:6)
这里没有特别的Spark特定于忽略可能的序列化问题。如果你想使用某个对象,它必须在当前范围内可用,你可以像往常一样实现这个目的:
您可以在已定义广播的范围内定义助手:
{
...
val x = sc.broadcast(1)
object Foo {
def foo = x.value
}
...
}
您可以将它用作构造函数参数:
case class Foo(x: org.apache.spark.broadcast.Broadcast[Int]) {
def foo = x.value
}
...
Foo(sc.broadcast(1)).foo
方法参数
case class Foo() {
def foo(x: org.apache.spark.broadcast.Broadcast[Int]) = x.value
}
...
Foo().foo(sc.broadcast(1))
甚至是这样的帮助者:
trait Foo {
val x: org.apache.spark.broadcast.Broadcast[Int]
def foo = x.value
}
object Main extends Foo {
val sc = new SparkContext("local", "test", new SparkConf())
val x = sc.broadcast(1)
def main(args: Array[String]) {
sc.parallelize(Seq(None)).map(_ => foo).first
sc.stop
}
}
答案 1 :(得分:1)
对前面介绍的性能注意事项进行简短介绍。
zero233提出的选项确实是在Scala中执行此类操作的非常优雅的方式。同时,重要的是要了解在分布式系统中使用某些模式的含义。
使用混合方法/使用封闭类状态的任何逻辑不是最好的主意。每当您在lambdas中使用封闭类的状态时,Spark都必须序列化外部对象。并非总是如此,但是最好写安全的代码,而不是有一天不小心炸毁整个集群。
意识到这一点,我个人会去将显式参数传递给方法,因为这不会导致外部类序列化(method argument
方法)。
答案 2 :(得分:0)
您可以使用类并将广播变量传递给类
你的psudo代码应如下所示:
object AppMain{
def main(args: Array[String]){
//...
val broadcastA = sc.broadcast(a)
//..
lines.foreach(rdd => {
val obj = new AppObject1(broadcastA)
rdd.filter(p => obj.apply(p))
rdd.count
})
}
}
class AppObject1(bc : Broadcast[String]){
val anotherObject = new AnotherObject(bc)
def apply(str: String): Boolean ={
anotherObject.process(str)
}
}
class AnotherObject(bc : Broadcast[String]){
// I want to use broadcast variable in this object
def process(str : String): Boolean = {
val a = bc.value
true
//need to use B inside this method
}
}