foreachRDD是否在驱动程序上执行?

时间:2016-07-22 12:48:34

标签: apache-spark spark-streaming

我正在尝试使用Spark Streaming处理在JMS队列(QPID)上收到的一些XML数据。将xml作为DStream后,我将它们转换为Dataframes,这样我就可以加入一些已加载的Dataframes形式的静态数据。 但是根据DStream上foreachRdd方法的API文档: 它在Driver上执行,所以这意味着所有处理逻辑只能在Driver上运行而不会分配给worker / executors。

API文档

  

foreachRDD(func)

     

应用a的最通用输出运算符   函数,func,从流生成的每个RDD。这个功能   应该将每个RDD中的数据推送到外部系统,例如保存   RDD到文件,或通过网络将其写入数据库。注意   函数func在运行的驱动程序进程中执行   流应用程序,通常会在其中有RDD操作   将强制计算流式RDD。

2 个答案:

答案 0 :(得分:12)

  

所以这意味着所有处理逻辑只能在Driver上运行而不是   分发给工人/执行者。

不,功能本身在驱动程序上运行,但不要忘记它在RDD上运行。您在RDD上使用的内部功能,例如foreachPartitionmapfilter仍将在工作节点上运行。这赢了会导致所有数据通过网络发送回驱动程序,除非您调用类似collect的方法。

答案 1 :(得分:5)

为了清楚说明,如果你运行以下内容,你会看到" monkey"关于司机的标准:

myDStream.foreachRDD { rdd =>
  println("monkey")
}

如果你运行以下内容,你会看到" monkey"在驱动程序的标准输出上,过滤器 工作 将在rdd分发的任何执行程序上完成:

myDStream.foreachRDD { rdd =>
  println("monkey")
  rdd.filter(element => element == "Save me!")
}

让我们添加myDStream只接收一个RDD的简化,并且此RDD分布在我们称之为PartitionSetA的一组分区上MachineSetB {1}}正在运行ExecutorSetC。如果您执行以下操作,您将看到" monkey"在司机的标准上,你会看到" turtle"在ExecutorSetC中的所有执行程序的stdouts(" turtle"每个分区将出现一次 - 许多分区可以在运行执行程序的机器上),以及两个过滤器的工作并且将在ExecutorSetC

之间完成添加操作
myDStream.foreachRDD { rdd =>
  println("monkey")
  rdd.filter(element => element == "Save me!")
  rdd.foreachPartition { partition =>
    println("turtle")
    val x = 1 + 1
  }
}

还有一点需要注意的是,在以下代码中,y最终将通过网络从驱动程序发送到ExecutorSetC rdd的所有val y = 2 myDStream.foreachRDD { rdd => println("monkey") rdd.filter(element => element == "Save me!") rdd.foreachPartition { partition => println("turtle") val x = 1 + 1 val z = x + y } }

val y = 2
val broadcastY = sc.broadcast(y)
myDStream.foreachRDD { rdd =>
  println("monkey")
  rdd.filter(element => element == "Save me!")
  rdd.foreachPartition { partition =>
    println("turtle")
    val x = 1 + 1
    val z = x + broadcastY.value
  }
}

为了避免这种开销,您可以使用广播变量,该变量仅将驱动程序中的值发送到执行程序一次。例如:

{{1}}

为了通过广播变量发送更复杂的内容,例如一旦实例化后不易序列化的对象,您可以看到以下博文:https://allegro.tech/2015/08/spark-kafka-integration.html