更改火花流输出的文件名

时间:2017-09-22 16:06:03

标签: apache-spark spark-streaming

以下简单程序从kafka流中读取并每隔5分钟写入CSV文件及其火花流。它使用命名约定 part-00000-f90bbc78-b847-41d4-9938-bdae89adb8eb.csv 生成文件,有没有办法可以更改名称以包含" DATETIMESTAMP" + GUID

请adivse。感谢。

我能够找到DatastreamReader的选项列表,但没有找到DatastreamWriter的选项

https://spark.apache.org/docs/latest/api/java/org/apache/spark/sql/streaming/DataStreamReader.html#csv-java.lang.String-

public static void main(String[] args) throws Exception {

    if (args.length == 0)
        throw new Exception("Usage program configFilename");
    String configFilename = args[0];

    addShutdownHook();

    ConfigLoader.loadConfig(configFilename);
    sparkSession = SparkSession
            .builder()
            .appName(TestKafka.class.getName())
            .master(ConfigLoader.getValue("master")).getOrCreate();
    SparkContext context = sparkSession.sparkContext();
    context.setLogLevel(ConfigLoader.getValue("logLevel"));

    SQLContext sqlCtx = sparkSession.sqlContext();
    System.out.println("Spark context established");

    DataStreamReader kafkaDataStreamReader = sparkSession.readStream()
            .format("kafka")
            .option("kafka.bootstrap.servers", ConfigLoader.getValue("brokers"))
            .option("group.id", ConfigLoader.getValue("groupId"))
            .option("subscribe", ConfigLoader.getValue("topics"))
            .option("failOnDataLoss", false);
    Dataset<Row> rawDataSet = kafkaDataStreamReader.load();
    rawDataSet.printSchema();
    rawDataSet.createOrReplaceTempView("rawEventView1");

    rawDataSet = rawDataSet.withColumn("rawEventValue", rawDataSet.col("value").cast("string"));
    rawDataSet.printSchema();
    rawDataSet.createOrReplaceTempView("eventView1");
    sqlCtx.sql("select * from eventView1")
            .writeStream()
            .format("csv")
            .option("header", "true")
            .option("delimiter", "~")
            .option("checkpointLocation", ConfigLoader.getValue("checkpointPath"))
            .option("path", ConfigLoader.getValue("recordsPath"))
            .outputMode(OutputMode.Append())
            .trigger(ProcessingTime.create(Integer.parseInt(ConfigLoader.getValue("kafkaProcessingTime"))
                    , TimeUnit.SECONDS))
            .start()
            .awaitTermination();
}

2 个答案:

答案 0 :(得分:2)

没有更改结构化Streaming中部分文件格式的规定,它使用ManifestFileCommitProtocol跟踪作业写入的有效文件列表。目标零件文件的名称是split,uuid和extension的组合,这是为了避免碰撞。

来源:https://github.com/apache/spark/blob/20adf9aa1f42353432d356117e655e799ea1290b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/ManifestFileCommitProtocol.scala#L87

答案 1 :(得分:1)

1)saveAsTextFile方法中没有直接支持来控制文件输出名称。您可以尝试使用saveAsHadoopDataset来控制输出文件basename。

例如:您可以获得yourCustomName-00000。而不是part-00000。

请记住,您无法使用此方法控制后缀00000。这是火花在写入时自动为每个分区分配的内容,以便每个分区写入一个唯一的文件。

为了控制注释中的上述内容,您必须编写自己的自定义OutputFormat。

SparkConf conf=new SparkConf();
conf.setMaster("local").setAppName("yello");
JavaSparkContext sc=new JavaSparkContext(conf);

JobConf jobConf=new JobConf();
jobConf.set("mapreduce.output.basename", "customName");
jobConf.set("mapred.output.dir", "outputPath");

JavaRDD<String> input = sc.textFile("inputDir");

input.saveAsHadoopDataset(jobConf);

2)解决方法是将输出原样写入输出位置,并使用Hadoop FileUtil.copyMerge function形成合并文件。