假设我有一个带有1个驱动程序和3个工作节点的Spark群集。我开始一项需要流媒体上下文(DStream)消耗Kafka主题消息的新工作,我需要多个(“竞争”)消费者线程,这些消费者线程都消费主题消息并对他们收到的消息进行一些处理。他们所做的工作是DataFrame密集型,这意味着要调用大量的DataFrame操作。当我了解 Spark场景时,无论何时调用DataFrame操作,Spark驱动程序都会在可用的工作节点上运行这些操作。
因此,给出以下代码和上述集群:
def createKafkaStream(ssc: StreamingContext,
kafkaTopics: String, brokers: String): DStream[(String,
String)] = {
// some configs here
KafkaUtils.createDirectStream[String, String, StringDecoder,
StringDecoder](ssc, props, topicsSet)
}
def consumerHandler(): StreamingContext = {
val ssc = new StreamingContext(sc, Seconds(10))
createKafkaStream(ssc, "someTopic", "my-kafka-ip:9092").foreachRDD(rdd => {
rdd.foreach { msg =>
// Now do some DataFrame-intensive work.
// As I understand things, DataFrame ops must be run
// on Workers as well as streaming consumers.
}
})
ssc
}
StreamingContext.getActive.foreach {
_.stop(stopSparkContext = false)
}
val ssc = StreamingContext.getActiveOrCreate(consumerHandler)
ssc.start()
ssc.awaitTermination()
...我担心工作节点上的争用(挂起/延迟/缓慢)。因为听起来像Spark和Kafka会弄清楚(基于分区)应该将多少流消费者线程部署到不同的工作节点。
因此,在3-Worker Node集群中,您可以想象有3个流式消费者流程正在运行,但在每个流程中,我们可以调用DataFrame操作。 由于所有工作人员已经“用完”作为流媒体消费者,因此没有工作人员可以执行DataFrame操作。
所以我问:这是一个合理的问题,还是Spark做了一些时间上的魔术来确保工作者(充当流媒体消费者)从不阻止或阻止DataFrame操作相互竞争?而且,如果这是一个问题,一般的解决方案是什么?更多工作节点?