为什么两个火花流式传输作业从相同的Kafka主题中获取具有相同组ID的消息,而不是平衡负载但获取相同的消息?

时间:2015-11-26 10:39:49

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

Kafka 0.8官方文件描述Kafka Consumer如下:

“消费者使用使用者组名称标记自己,并且发布到主题的每条消息都会传递到每个订阅使用者组中的一个使用者实例。使用者实例可以位于不同的进程中,也可以位于不同的计算机上。 如果所有的消费者实例都具有相同的消费者群体,那么这就像传统的队列平衡对消费者的负载一样。“

我使用Kafka 0.8.1.1设置了一个Kafka集群,并使用Spark Streaming作业(spark 1.3)从其主题中提取数据。 Spark Streaming代码如下:

    ... ...

    HashMap<String, String> kafkaParams = new HashMap<String, String>();
    kafkaParams.put("metadata.broker.list", brokerList);
    kafkaParams.put("group.id", groupId);

    JavaPairInputDStream<String, String> messages = KafkaUtils.createDirectStream(
                jssc,
                String.class,
                String.class,
                StringDecoder.class,
                StringDecoder.class,
                kafkaParams,
                topicsSet
        );

    messages.foreachRDD(new Function<JavaPairRDD<String, String>, Void>() {

        @Override
        public Void call(JavaPairRDD<String, String> rdd) throws Exception {
            long msgNum = strJavaRDD.count();
            System.out.println("There are " + msgNum + " messages read from Kafka.");

        ... ...

        return null;}});

然后我提交了两个Spark Streaming作业来访问具有相同组ID的相同主题。我假设当我向主题发送100条消息时,这两个作业总共获得100条消息(例如,job1获得50,job2获得50;或job1获得100,job2获得0)。但是,他们分别得到100。这样的结果似乎与卡夫卡医生说的不同。

我的代码有什么问题吗?我是否正确设置了组ID配置?这是createDirectStream()的错误还是设计?

测试环境:Kafka 0.8.1.1 + Spark 1.3.1

2 个答案:

答案 0 :(得分:0)

Group是Kafka在0.9版之前的高级消费者API的一个功能,它在简单的使用API​​中不可用。 createDirectStream使用简单的消费者API。

一些提示:

  1.   

    使用SimpleConsumer实现的主要原因是您希望更好地控制分区消耗,而不是消费者组给您的。 (EG:多次阅读邮件)

  2.   

    createDirectStream:此方法不是使用接收器接收数据,而是定期向Kafka查询每个主题+分区中的最新偏移量,并相应地定义要在每个批次中处理的偏移量范围。

  3. 参见:

    1. Spark Streaming + Kafka Integration Guide
    2. 0.8.0 SimpleConsumer Example
    3. Kafka 0.9.0版本添加了一个新的Java消费者来替换现有的基于ZooKeeper的高级消费者和低级消费者API。然后你可以使用group并同时提交偏移手册。

答案 1 :(得分:0)

使用相同的消息创建两个不同的spark应用程序来做同样的事情是没有意义的。使用一个具有更多执行程序的应用程序。