将spark作业启动到独立群集时的java.lang.NullPointerException

时间:2018-02-26 07:48:25

标签: apache-spark

我有以下代码:

  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

1 个答案:

答案 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
}

我希望答案很有帮助