【问题标题】:Kafka Spark streaming: unable to read messagesKafka Spark 流式传输:无法读取消息
【发布时间】:2015-01-26 18:16:38
【问题描述】:

我正在使用 spark-streaming 集成 Kafka 和 Spark。我作为 kafka 制作人创建了一个主题:

bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test 

我在 kafka 中发布消息并尝试使用 spark-streaming java 代码读取它们并将它们显示在屏幕上。
守护进程全部启动:Spark-master,worker;动物园管理员;卡夫卡。
我正在编写一个 java 代码,使用 KafkaUtils.createStream
代码如下:

public class SparkStream {
    public static void main(String args[])
    {
        if(args.length != 3)
        {
            System.out.println("SparkStream <zookeeper_ip> <group_nm> <topic1,topic2,...>");
            System.exit(1);
        }


        Map<String,Integer> topicMap = new HashMap<String,Integer>();
        String[] topic = args[2].split(",");
        for(String t: topic)
        {
            topicMap.put(t, new Integer(1));
        }

        JavaStreamingContext jssc = new JavaStreamingContext("spark://192.168.88.130:7077", "SparkStream", new Duration(3000));
        JavaPairReceiverInputDStream<String, String> messages = KafkaUtils.createStream(jssc, args[0], args[1], topicMap );

        System.out.println("Connection done++++++++++++++");
        JavaDStream<String> data = messages.map(new Function<Tuple2<String, String>, String>() 
                                                {
                                                    public String call(Tuple2<String, String> message)
                                                    {
                                                        System.out.println("NewMessage: "+message._2()+"++++++++++++++++++");
                                                        return message._2();
                                                    }
                                                }
                                                );
        data.print();

        jssc.start();
        jssc.awaitTermination();

    }
}

我正在运行作业,而在其他终端我正在运行 kafka-producer 来发布消息:

Hi kafka
second message
another message

但是 spark-streaming 控制台的输出日志不显示消息,但显示接收到零块:

-------------------------------------------
Time: 1417438988000 ms
-------------------------------------------

2014-12-01 08:03:08,008 INFO  [sparkDriver-akka.actor.default-dispatcher-4] scheduler.JobScheduler (Logging.scala:logInfo(59)) - Starting job streaming job 1417438988000 ms.0 from job set of time 1417438988000 ms
2014-12-01 08:03:08,008 INFO  [sparkDriver-akka.actor.default-dispatcher-4] scheduler.JobScheduler (Logging.scala:logInfo(59)) - Finished job streaming job 1417438988000 ms.0 from job set of time 1417438988000 ms
2014-12-01 08:03:08,009 INFO  [sparkDriver-akka.actor.default-dispatcher-4] scheduler.JobScheduler (Logging.scala:logInfo(59)) - Total delay: 0.008 s for time 1417438988000 ms (execution: 0.000 s)
2014-12-01 08:03:08,010 INFO  [sparkDriver-akka.actor.default-dispatcher-15] scheduler.JobScheduler (Logging.scala:logInfo(59)) - Added jobs for time 1417438988000 ms
2014-12-01 08:03:08,015 INFO  [sparkDriver-akka.actor.default-dispatcher-15] rdd.MappedRDD (Logging.scala:logInfo(59)) - Removing RDD 39 from persistence list
2014-12-01 08:03:08,024 INFO  [sparkDriver-akka.actor.default-dispatcher-4] storage.BlockManager (Logging.scala:logInfo(59)) - Removing RDD 39
2014-12-01 08:03:08,027 INFO  [sparkDriver-akka.actor.default-dispatcher-15] rdd.BlockRDD (Logging.scala:logInfo(59)) - Removing RDD 38 from persistence list
2014-12-01 08:03:08,031 INFO  [sparkDriver-akka.actor.default-dispatcher-2] storage.BlockManager (Logging.scala:logInfo(59)) - Removing RDD 38
2014-12-01 08:03:08,033 INFO  [sparkDriver-akka.actor.default-dispatcher-15] kafka.KafkaInputDStream (Logging.scala:logInfo(59)) - Removing blocks of RDD BlockRDD[38] at BlockRDD at ReceiverInputDStream.scala:69 of time 1417438988000 ms
2014-12-01 08:03:09,002 INFO  [sparkDriver-akka.actor.default-dispatcher-2] scheduler.ReceiverTracker (Logging.scala:logInfo(59)) - Stream 0 received 0 blocks

为什么没有收到数据块?我曾尝试在控制台bin/kafka-console-producer....bin/kafka-console-consumer... 上使用kafka producer-consumer,它的工作完美,但为什么不是我的代码......任何想法?

【问题讨论】:

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


    【解决方案1】:

    问题已解决。

    上面的代码是正确的。 我们将只添加两行来抑制生成的 [INFO] 和 [WARN]。所以最终的代码是:

    package com.spark;
    
    import scala.Tuple2;
    import org.apache.log4j.Logger;
    import org.apache.log4j.Level;
    import kafka.serializer.Decoder;
    import kafka.serializer.Encoder;
    import org.apache.spark.streaming.Duration;
    import org.apache.spark.*;
    import org.apache.spark.api.java.function.*;
    import org.apache.spark.api.java.*;
    import org.apache.spark.streaming.kafka.KafkaUtils;
    import org.apache.spark.streaming.kafka.*;
    import org.apache.spark.streaming.api.java.JavaStreamingContext;
    import org.apache.spark.streaming.api.java.JavaPairDStream;
    import org.apache.spark.streaming.api.java.JavaDStream;
    import org.apache.spark.streaming.api.java.JavaPairReceiverInputDStream;
    import java.util.Map;
    import java.util.HashMap;
    
    public class SparkStream {
        public static void main(String args[])
        {
            if(args.length != 3)
            {
                System.out.println("SparkStream <zookeeper_ip> <group_nm> <topic1,topic2,...>");
                System.exit(1);
            }
    
            Logger.getLogger("org").setLevel(Level.OFF);
            Logger.getLogger("akka").setLevel(Level.OFF);
            Map<String,Integer> topicMap = new HashMap<String,Integer>();
            String[] topic = args[2].split(",");
            for(String t: topic)
            {
                topicMap.put(t, new Integer(3));
            }
    
            JavaStreamingContext jssc = new JavaStreamingContext("local[4]", "SparkStream", new Duration(1000));
            JavaPairReceiverInputDStream<String, String> messages = KafkaUtils.createStream(jssc, args[0], args[1], topicMap );
    
            System.out.println("Connection done++++++++++++++");
            JavaDStream<String> data = messages.map(new Function<Tuple2<String, String>, String>() 
                                                    {
                                                        public String call(Tuple2<String, String> message)
                                                        {
                                                            return message._2();
                                                        }
                                                    }
                                                    );
            data.print();
    
            jssc.start();
            jssc.awaitTermination();
    
        }
    }
    

    另外我们需要在 POM.xml 中添加依赖:

    <dependency>
    <groupId>com.msiops.footing</groupId>
    <artifactId>footing-tuple</artifactId>
    <version>0.2</version>
    </dependency>  
    

    此依赖项用于使用scala.Tuple2
    Stream 0 received 0 block 的错误是由于 spark-worker 不可用并且 spark-worker-core 设置为 1。对于 spark-streaming,我们需要核心 >=2。 所以我们需要在 spark-config 文件中进行更改。请参阅安装手册。添加行export SPARK_WORKER_CORE=5 还将SPARK_MASTER='hostname' 更改为SPARK_MASTER=&lt;your local IP&gt;。当您转到 Spark UI Web 控制台时,此本地 IP 以粗体显示...类似于:spark://192.168..:&lt;port&gt;。我们不需要这里的端口。只需要 IP。
    现在重新启动您的 spark-master 和 spark-worker 并开始流式传输:)

    输出:

    -------------------------------------------
    Time: 1417443060000 ms
    -------------------------------------------
    message 1
    
    -------------------------------------------
    Time: 1417443061000 ms
    -------------------------------------------
    message 2
    
    -------------------------------------------
    Time: 1417443063000 ms
    -------------------------------------------
    message 3
    message 4
    
    -------------------------------------------
    Time: 1417443064000 ms
    -------------------------------------------
    message 5
    message 6
    messag 7
    
    -------------------------------------------
    Time: 1417443065000 ms
    -------------------------------------------
    message 8
    

    【讨论】:

    • @aiman- 你能详细说明你的答案吗?哪个火花配置文件。在哪里可以找到这个文件?
    • 更改每个节点上的核心数(conf/spark-env.sh 脚本)或在 conf/spark-defaults.conf 中全局更改
    【解决方案2】:

    是的,您需要从 DStream 访问内容。

    messages.foreachRDD(<<processing for the input received in the interval>>);
    

    【讨论】:

    • 嗨维杰。我已经添加了行messages.print()。那不行吗?如何在 foreachRDD() 中使用打印逻辑?
    • 嗨 Vijay,根据您的建议,我编辑了上面的代码,即添加了这些行:
    • JavaDStream data = messages.map(new Function, String>() { public String call(Tuple2 message) { System.out. println("NewMessage: "+message._2()); 返回消息._2(); } } );数据.print();
    • 但是输出还是一样:Stream 0收到了0 blocks
    猜你喜欢
    • 2018-06-25
    • 1970-01-01
    • 2019-01-29
    • 2016-06-21
    • 2015-12-12
    • 1970-01-01
    • 1970-01-01
    • 2018-01-09
    • 1970-01-01
    相关资源
    最近更新 更多