从Spark串行消费Kafka主题

时间:2016-08-15 19:35:25

标签: scala apache-spark apache-kafka spark-streaming

给出以下代码:

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将自动协同工作以确定要部署到可用工作节点的消费者线程数量,这可能导致并行处理Kafka主题的消息。

但如果我想要多个并行消费者呢?如果希望1和1的消费者从主题中读取下一条消息,完全处理它,然后重新开始并轮询下一条消息,那该怎么办呢?

另外,当我打电话时:

val ssc = new StreamingContext(sc, Seconds(10))

这是否意味着:

  • 单个消费者线程将收到在过去10秒内发布到该主题的所有消息;
  • 单个使用者线程是否会收到该主题的下一条(单个)消息,并且它将每10秒轮询一次下一条消息?

1 个答案:

答案 0 :(得分:2)

  

但是,如果我不想要多个并行消费者呢?如果想要怎么办   1和1的消费者阅读主题中的下一条消息,   完全处理它,然后重新开始   轮询下一条消息。

如果这是你的用例,我会说为什么要使用Spark呢?它的全部优点是您可以并行读取。我能想到的唯一的hacky解决方法是使用单个分区创建一个Kafka主题,这会使Spark将整个偏移范围分配给单个工作者,但这很难看。

  

这是否意味着单个消费者线程将接收所有消息   在最近10秒内发布到该主题或单个   消费者线程将从主题接收下一条(单个)消息,   并且它将每10秒轮询下一条消息?

都不是。由于您使用直接(无接收器)流方法,这意味着每10秒,您的驱动程序将要求Kafka为他提供自上一批次以来已更改的偏移范围,对于所述主题的每个分区。然后,Spark将采用每个这样的偏移范围,并将其发送给其中一个工人直接从Kafka消费。这意味着使用直接流方法,Kafka分区与Spark分区之间存在1:1的对应关系。