我正在开发一个火花流媒体作业(使用不使用DStreams的结构化流媒体)。我从kafka收到一条消息,其中包含许多带逗号分隔值的字段,其中第一列是文件名。现在基于该文件名,我将不得不从HDFS读取文件并创建数据帧并进一步操作。这似乎很简单,但是火花不允许我在调用start之前运行任何动作。 Spark Documentation也引用了相同的内容。
此外,还有一些数据集方法无法使用 流数据集。它们是立即运行查询的操作 并返回结果,这对流式数据集没有意义。
以下是我的尝试。
object StructuredStreamingExample {
case class filenameonly(value:String)
def main(args:Array[String])
{
val spark = SparkSession.builder.appName("StructuredNetworkWordCount").master("local[*]").getOrCreate()
spark.sqlContext.setConf("spark.sql.shuffle.partitions", "5")
import spark.implicits._
val lines = spark
.readStream
.format("kafka")
.option("kafka.bootstrap.servers", "localhost:9092")
.option("subscribe", "strtest")
.load()
val values=lines.selectExpr("CAST(value AS STRING)").as[String]
val filename = values.map(x => x.split(",")(0)).toDF().select($"value")
//Here how do i convert the filename which is a Dataframe to string and apply that to spark.readtextfile(filename)
datareadfromhdfs
.writeStream
.trigger(ProcessingTime("10 seconds"))
.outputMode("append")
.format("console")
.start()
.awaitTermination()
现在在上面的代码中,我得到的文件名是一个Dataframe,如何将其转换为String,以便我可以执行spark.readtextfile(filename)来读取HDFS中的文件。
答案 0 :(得分:0)
我不确定它是否能最好地用于火花流,但在这种情况下,我会调用filename.foreachRDD并从那里读取hdfs文件并执行您需要的任何操作。
(请记住,在foreachRDD中运行时,您不能使用全局spark会话,但需要从构建器中获取或者创建它:val sparkSession = SparkSession.builder.config(myCurrentForeachRDD.sparkContext.getConf).getOrCreate()
)
您似乎依赖于流来告诉您在哪里查看和加载文件。您是否尝试过在该文件夹上使用文件流并让spark自动监视并自动读取新文件?
答案 1 :(得分:0)
使用spark结构化流媒体肯定不是最好的用例。如果您正确理解了spark结构化流,那么所有数据转换/聚合都应该在生成结果表的查询上进行。但是,您仍然可以实现一些解决方法,您可以编写代码以从(falt)mapWithGroupState中的HDFS读取数据。但是,同样不建议这样做。