我有一个火花流媒体应用程序,如下所示:
val message = KafkaUtils.createStream(...).map(_._2)
message.foreachRDD( rdd => {
if (!rdd.isEmpty){
val kafkaDF = sqlContext.read.json(rdd)
kafkaDF.foreachPartition(
i =>{
createConnection()
i.foreach(
row =>{
connection.sendToTable()
}
)
closeConnection()
}
)
并且,我使用
在纱线群集上运行它spark-submit --master yarn-cluster --num-executors 3 --driver-memory 2g --executor-memory 2g --executor-cores 5....
当我尝试记录kafkaDF.rdd.partitions.size
时,结果大多为“1”或“5”。我很困惑,是否可以控制我的DataFrame的分区数量? KafkaUtils.createStream
似乎不接受任何与我想要的rdd分区数相关的参数。我试过了kafkaDF.rdd.repartition( int )
,但它似乎也没有用。
如何在代码中实现更多并行性?如果我的方法是错误的,那么实现它的正确方法是什么?
答案 0 :(得分:5)
在Spark Streaming中,可以在两个方面实现并行性:(a)消费者/接收者(在您的情况下是Kafka消费者),以及(b)处理(由Spark完成)。
默认情况下,spark streaming会为每个消费者分配一个核心(也就是Thread)。因此,如果您需要获取更多数据,则需要创建更多消费者。每个消费者都将创建一个DStream。然后,您可以将DStream联合以获取一个大流。
// A basic example with two threads for consumers
val messageStream1 = KafkaUtils.createStream(...) // say, reading topic A
val messageStream2 = KafkaUtils.createStream(...) // and this one reading topic B
val combineStream = messageStream1.union(messageStream2)
Alternatively,通过重新分区输入流可以增加接收者/消费者的数量:
inputStream.repartition(<number of partitions>))
流式应用程序可用的所有剩余核心都将分配给Spark。
因此,如果您拥有N
个核心(通过spark.cores.max
定义),并且您拥有C
个消费者,那么您可以使用N-C
核心。
#Partitions =~ #Consumers x (batch duration / block interval)
阻止间隔 =消费者在将其创建的数据作为火花块(定义为配置spark.streaming.blockInterval
)推送之前等待的时间。
请记住,Spark Streaming有两个不断发生的功能。一组读取当前微批(消费者)的线程,以及一组处理前一个微批(Spark)的线程。