我有以下代码:
val spark = SparkSession.builder
.appName("Simple Application")
.master("spark://myserver.com:7077")
//.master("local[*]") //notice this line
.getOrCreate()
val sc = spark.sparkContext
val arr: RDD[(Int, Int)] = sc.parallelize(Array( 1->2 , 3 -> 4, 5 -> 4, 1->2 , 3 -> 4, 5 -> 4,7 -> 8))
val arr2: RDD[(Int, String)] = sc.parallelize(Array( 1->"a" , 2 -> "b", 3 -> "c"))
val map = arr2.take(arr2.count().toInt).toMap
val result1 = arr map { case (a,b) =>
if ( map.contains(a) ) map(a) -> b
else "other" -> b
}
result1 take 100000 foreach println
当我将其发送到spark://myserver.com:7077
时,我收到了错误消息:
第java.lang.NullPointerException
行的if ( map.contains(a) ) ...
事实证明,对象map
为空。
但是,当我使用' .master("本地[*]"'启动它时,它运行正常。
我在同一节点上启动了主服务器和从服务器。
为什么我得到NullPointerException
?
答案 0 :(得分:0)
在群集模式中,当您将map
之类的变量声明为
val map = arr2.take(arr2.count().toInt).toMap
只能在驱动程序节点中访问,并且在执行映射函数调用时未映射到每个执行程序节点
val result1 = arr map { case (a,b) =>
if ( map.contains(a) ) map(a) -> b
else "other" -> b
}
因此执行程序节点将无法识别映射变量是什么。您必须找到一种方法将映射变量分发到执行程序节点。其中一种方法是使用广播变量(如果变量引用的数据足够小)并在map
函数中使用它,以便执行者可以在需要时调用它们。 p>
val map = sc.broadcast(arr2.take(arr2.count().toInt).toMap)
val result1 = arr map { case (a,b) =>
if ( map.value.contains(a) ) map.value(a) -> b
else "other" -> b
}
我希望答案很有帮助