Spark Streaming中的Spark SQL失败(KafkaStream)

时间:2016-08-22 13:12:37

标签: java hadoop apache-spark apache-spark-sql spark-streaming

我在Spark Streaming Job中使用Spark SQL来搜索Hive表。 Kafka流媒体工作正常没有问题。如果我在hiveContext.runSqlHive(sqlQuery);之外运行directKafkaStream.foreachRDD,它可以正常运行而不会出现问题。但是我需要在流媒体作业中进行Hive-Table查找。使用JDBC(jdbc:hive2://)会起作用,但我想使用Spark SQL。

我的源代码的重要位置如下所示:

// set context
SparkConf sparkConf = new SparkConf().setAppName(appName).set("spark.driver.allowMultipleContexts", "true");
SparkContext sparkSqlContext = new SparkContext(sparkConf);
JavaStreamingContext streamingContext = new JavaStreamingContext(sparkConf, Durations.seconds(batchDuration));
HiveContext hiveContext = new HiveContext(sparkSqlContext);

// Initialize Direct Spark Kafka Stream. Starts from top
JavaPairInputDStream<String, String> directKafkaStream =
                KafkaUtils.createDirectStream(streamingContext,
                        String.class,
                        String.class,
                        StringDecoder.class,
                        StringDecoder.class,
                        kafkaParams,
                        topicsSet);

// work on stream                   
directKafkaStream.foreachRDD((Function<JavaPairRDD<String, String>, Void>) rdd -> {
    rdd.foreachPartition(tuple2Iterator -> {
        // get message
        Tuple2<String, String> item = tuple2Iterator.next();

        // lookup
        String sqlQuery = "SELECT something FROM somewhere";
        Seq<String> resultSequence = hiveContext.runSqlHive(sqlQuery);
        List<String> result = scala.collection.JavaConversions.seqAsJavaList(resultSequence);

        });
    return null;
});

// Start the computation
streamingContext.start();
streamingContext.awaitTermination();            

即使我使用try-catch包围,也没有任何有意义的错误。

我希望有人可以提供帮助 - 谢谢。

//编辑: 解决方案如下:

// work on stream                   
directKafkaStream.foreachRDD((Function<JavaPairRDD<String, String>, Void>) rdd -> {
    // driver
    Map<String, String> lookupMap = getResult(hiveContext); //something with hiveContext.runSqlHive(sqlQuery);
    rdd.foreachPartition(tuple2Iterator -> {
        // worker
        while (tuple2Iterator != null && tuple2Iterator.hasNext()) {
            // get message
            Tuple2<String, String> item = tuple2Iterator.next();
            // lookup
            String result = lookupMap.get(item._2());
        }
    });
    return null;
});

1 个答案:

答案 0 :(得分:1)

只是因为你想使用Spark SQL它不会让它成为可能。 Spark的第一条规则是没有嵌套的动作,转换或分布式数据结构。

如果您可以将您的查询表达为例如连接,则可以使用将其推送到更高级别String[] PERMISSIONS = {Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE}; if(!hasPermissions(this, PERMISSIONS)){ ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL); } 的一个级别,这非常耗尽您在此处使用Spark SQL的选项:

foreachRDD

否则直接JDBC连接可以是有效选项。