来自Kafka的Spark Streaming和以Avro格式写入HDFS

时间:2017-10-08 09:34:39

标签: scala apache-spark hdfs spark-streaming avro

我基本上想要从Kafka使用数据并将其写入HDFS。但事实是,它不是在hdfs中写入任何文件。它创建空文件。

如果我想在hdfs中以avro格式编写,我还可以指导我如何修改代码。

为了简单起见,写入本地C盘。

import org.apache.spark.SparkConf
import org.apache.kafka.common.serialization.StringDeserializer
import org.apache.spark.SparkContext
import org.apache.spark.streaming.Seconds
import org.apache.spark.streaming.StreamingContext
import org.apache.spark.streaming.kafka010.ConsumerStrategies.Subscribe
import org.apache.spark.streaming.kafka010.KafkaUtils
import 
org.apache.spark.streaming.kafka010.LocationStrategies.PreferConsistent
import org.apache.kafka.common.serialization.StringDeserializer

object KafkaStreaming extends App{
val conf = new org.apache.spark.SparkConf().setMaster("local[*]").setAppName("kafka-streaming")
val conext = new SparkContext(conf)
val ssc = new StreamingContext(conext, org.apache.spark.streaming.Milliseconds(1))
val kafkaParams = Map[String, Object](
  "bootstrap.servers" -> "localhost:9092",
  "key.deserializer" -> classOf[StringDeserializer],
  "value.deserializer" -> classOf[StringDeserializer],
  "group.id" -> "group",
  "auto.offset.reset" -> "latest",
  "enable.auto.commit" -> (true: java.lang.Boolean))
val topics = Array("topic")
val stream = KafkaUtils.createDirectStream[String, String](
  ssc,
  PreferConsistent,
  Subscribe[String, String](topics, kafkaParams))
val lines = stream.map(_.value)
stream.foreachRDD(rdd => {
  rdd.coalesce(1).saveAsTextFile("C:/data/spark/")
})
ssc.start()
ssc.awaitTermination()}

以下是build.sbt

name := "spark-streaming"
version := "1.0"
scalaVersion := "2.11.8" 
libraryDependencies += "org.apache.spark" % "spark-core_2.11" % "2.2.0"
libraryDependencies += "org.apache.spark" % "spark-streaming_2.11" % "2.2.0"
libraryDependencies += "org.apache.spark" % "spark-streaming-kafka-0-
10_2.11" % "2.2.0"
libraryDependencies += "org.apache.kafka" % "kafka-clients" % "0.11.0.1"

4 个答案:

答案 0 :(得分:1)

  

不在hdfs中写入任何文件。它会创建空文件。

请检查如何调试

Unable to see messages from Kafka Stream in Spark

  

如果我想在hdfs中用avro格式写

,请指导我

https://github.com/sryza/simplesparkavroapp

package com.cloudera.sparkavro

import org.apache.avro.mapred.AvroKey
import org.apache.avro.mapreduce.{AvroJob, AvroKeyOutputFormat}
import org.apache.hadoop.fs.Path
import org.apache.hadoop.io.NullWritable
import org.apache.hadoop.mapreduce.Job
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.SparkContext._

object SparkSpecificAvroWriter {
  def main(args: Array[String]) {
    val outPath = args(0)

    val sparkConf = new SparkConf().setAppName("Spark Avro")
    MyKryoRegistrator.register(sparkConf)
    val sc = new SparkContext(sparkConf)

    val user1 = new User("Alyssa", 256, null)
    val user2 = new User("Ben", 7, "red")

    val records = sc.parallelize(Array(user1, user2))
    val withValues = records.map((x) => (new AvroKey(x), NullWritable.get))

    val conf = new Job()
    FileOutputFormat.setOutputPath(conf, new Path(outPath))
    val schema = User.SCHEMA$
    AvroJob.setOutputKeySchema(conf, schema)
    conf.setOutputFormatClass(classOf[AvroKeyOutputFormat[User]])
    withValues.saveAsNewAPIHadoopDataset(conf.getConfiguration)
  }
}

答案 1 :(得分:1)

看到您的代码,您只需将当前时间戳附加到您正在编写的文件中即可。

那应该可以解决你的问题。 :)

==========

如果要将所有文件附加到一个文件中,则可以使用如下的数据框:

由于这个文件系统的设计方式,我不建议在HDFS中使用append。但这是你可以尝试的。

  1. 从RDD创建数据框
  2. 使用Dataframe的保存模式(“append”)然后写入文件。
  3. e.g:

    val dataframe = youRdd.toDF(); 。dataframe.write()模式(SaveMode.Append).format(FILE_FORMAT)..保存(路径);

    看看是否有帮助

答案 2 :(得分:0)

下运行Kafka消费者应用程序之前,您必须检查:

  • 检查数据是否在Kafka中可用

  • auto.offset.reset更改为earliest    这里最早意味着kafka会自动将偏移重置为最早的偏移量。

  • 启动Kafka控制台生产者应用程序并开始输入一些消息。然后启动您的Kafka消费者代码,再次在Kafka控制台生产者上键入一些消息,然后检查消息是否正在打印到消费者控制台。

您可以使用以下代码行以avro格式编写输出

spark.write.avro("<path>")

我希望这会对你有所帮助

答案 3 :(得分:0)

改成 "auto.offset.reset" -> "最新",

"auto.offset.reset" -> "最早",