我真的在这里绝望了。
我要做的是捕获流,聚合流数据几秒钟,然后将其保存为CSV文件。
val sparkSession : SparkSession = SparkSession.builder()
.master("local[*]")
.appName("Streaming")
.config(conf)
//.enableHiveSupport()
.getOrCreate()
所以,我正在捕捉流
val lines = streamingContext.socketTextStream(HOST, PORT)
val linesMessage = lines.map(_.split(DELIMITER)(1))
并计算事件
val counts = linesMessage.map(tag => (tag, 1))
.reduceByKeyAndWindow({ (x, y) => x + y }, { (x, y) => x - y }, Seconds(EVENT_PERIOD_SECONDS*4), Seconds(EVENT_PERIOD_SECONDS))
到目前为止工作。
现在,我想将每个windowLength保存在CSV文件中,然后卡在那里:
val schema = new StructType()
.add(StructField("text", StringType, true))
.add(StructField("count", IntegerType, true))
counts.foreachRDD(rdd =>
{
//rdd.saveAsTextFile(CHECKPOINT_DIR + "/output_" + sdf.format(System.currentTimeMillis()))
val df = sparkSession.createDataFrame(rdd.map(attributes => Row(attributes._1, attributes._2)), schema)
df.write.format("csv").save(CHECKPOINT_DIR + "/output_" + sdf.format(System.currentTimeMillis()))
})
有人可以帮助我吗?
抱歉,收到错误:
当我运行rdd.saveAsTextFile时,它会创建必须合并的各种纯文本文件。
通过创建createDataFrame会出现此错误
17/11/12 23:06:04 ERROR JobScheduler: Error running job streaming job 1510490490000 ms.1
java.lang.NullPointerException
at org.apache.spark.sql.SparkSession.sessionState$lzycompute(SparkSession.scala:128)
at org.apache.spark.sql.SparkSession.sessionState(SparkSession.scala:126)
at org.apache.spark.sql.Dataset$.ofRows(Dataset.scala:65)
at org.apache.spark.sql.SparkSession.createDataFrame(SparkSession.scala:578)
at org.apache.spark.sql.SparkSession.createDataFrame(SparkSession.scala:335)
at main.scala.Main$$anonfun$main$scala$Main$$functionToCreateContext$1$1.apply(Main.scala:152)
at main.scala.Main$$anonfun$main$scala$Main$$functionToCreateContext$1$1.apply(Main.scala:146)
第146行是sparkSession.createDataFrame行
答案 0 :(得分:0)
可能的原因和解决方法
问题可能来自sparkSession
,可能会与streamingContext
分开。
可能值得尝试从streamingContext
获取spark会话以确保两者共享相同的配置:
counts.foreachRDD(rdd => {
val spark = sparkSession.builder.config(streamingContext.sparkContext.getConf).getOrCreate()
val df = spark.createDataFrame(rdd.map(attributes => Row(attributes._1, attributes._2)), schema)
...
})
<强> Partioning 强>
如评论中所述,如果您的目标是减少Spark创建的文件数量,则只需在直接提供给您的函数的repartition
上使用RDD
:
counts.foreachRDD(rdd => {
rdd.repartition(10)
.saveAsTextFile(CHECKPOINT_DIR + "/output_" + sdf
.format(System.currentTimeMillis()))
})
repartition
应该非常谨慎地使用,因为您需要对结果分区的大小进行很好的估计,以避免不足或过大。
答案 1 :(得分:0)
我通过更改我的代码来“解决”它:
linesFilter.window(Seconds(EVENT_PERIOD_SECONDS*WRITE_EVERY_N_SECONDS), Seconds(EVENT_PERIOD_SECONDS*WRITE_EVERY_N_SECONDS)).foreachRDD { (rdd, time) =>
if (rdd.count() > 0) {
rdd
.coalesce(1,true)
.map(_.replace(DELIMITER_STREAM, DELIMITER_OUTPUT))
//.map{_.mkString(DELIMITER_OUTPUT) }
.saveAsTextFile(CHECKPOINT_DIR + "/output/o_" + sdf.format(System.currentTimeMillis()))
}
}