【发布时间】:2018-03-07 11:22:34
【问题描述】:
我正在使用 Java。
我正在通过 Kafka 消息接收文件路径。我需要将此文件加载到 spark RDD 中,对其进行处理,然后将其转储到 HDFS 中。
我能够从 Kafka 消息中检索文件路径。我希望在这个文件上创建一个数据集/RDD。
我无法在 Kafka 消息数据集上运行地图功能。 NPE 出错,因为 sparkContext 在 worker 上不可用。
我无法在 Kafka 消息数据集上运行 foreach。它出错并显示消息:
Queries with streaming sources must be executed with writeStream.start();"
我不能 collect 从 kafka 消息数据集接收到的数据,因为它会出现消息错误
Queries with streaming sources must be executed with writeStream.start();;
我想这一定是一个非常普遍的用例,并且必须在很多设置中运行。
如何从我在 Kafka 消息中收到的路径将文件加载为 RDD?
SparkSession spark = SparkSession.builder()
.appName("MyKafkaStreamReader")
.master("local[4]")
.config("spark.executor.memory", "2g")
.getOrCreate();
// Create DataSet representing the stream of input lines from kafka
Dataset<String> kafkaValues = spark.readStream()
.format("kafka")
.option("spark.streaming.receiver.writeAheadLog.enable", true)
.option("kafka.bootstrap.servers", Configuration.KAFKA_BROKER)
.option("subscribe", Configuration.KAFKA_TOPIC)
.option("fetchOffset.retryIntervalMs", 100)
.option("checkpointLocation", "file:///tmp/checkpoint")
.load()
.selectExpr("CAST(value AS STRING)").as(Encoders.STRING());
Dataset<String> messages = kafkaValues.map(x -> {
ObjectMapper mapper = new ObjectMapper();
String m = mapper.readValue(x.getBytes(), String.class);
return m;
}, Encoders.STRING() );
// ====================
// TEST 1 : FAILS
// ====================
// CODE TRYING TO execute MAP on the received RDD
// This fails with a Null pointer exception because "spark" is not available on worker node
/*
Dataset<String> statusRDD = messages.map(message -> {
// BELOW STATEMENT FAILS
Dataset<Row> fileDataset = spark.read().option("header", "true").csv(message);
Dataset<Row> dedupedFileDataset = fileDataset.dropDuplicates();
dedupedFileDataset.rdd().saveAsTextFile(getHdfsLocation());
return getHdfsLocation();
}, Encoders.STRING());
StreamingQuery query2 = statusRDD.writeStream().outputMode("append").format("console").start();
*/
// ====================
// TEST 2 : FAILS
// ====================
// CODE BELOW FAILS WITH EXCEPTION
// "Queries with streaming sources must be executed with writeStream.start();;"
// Hence, processing the deduplication on the worker side using
/*
JavaRDD<String> messageRDD = messages.toJavaRDD();
messageRDD.foreach( message -> {
Dataset<Row> fileDataset = spark.read().option("header", "true").csv(message);
Dataset<Row> dedupedFileDataset = fileDataset.dropDuplicates();
dedupedFileDataset.rdd().saveAsTextFile(getHdfsLocation());
});
*/
// ====================
// TEST 3 : FAILS
// ====================
// CODE TRYING TO COLLECT ALSO FAILS WITH EXCEPTION
// "Queries with streaming sources must be executed with writeStream.start();;"
// List<String> mess = messages.collectAsList();
关于如何读取创建文件路径并在文件上创建 RDD 的任何想法?
【问题讨论】:
-
我认为您无法使用结构化流实现此用例。将 Spark Streaming 与
Directkafka 消费者一起使用。您可以在通用foreachRDD操作中实现自定义文件加载逻辑。
标签: java apache-spark apache-kafka spark-structured-streaming