Spark Streaming程序将统计结果写入本地文件系统

背景

需要实时接收kafka topic中的消息,经spark streaming进行统计分析后,将统计结果写到本地文件系统,经由FTP发送给下游。
难点在于,Spark Streaming的程序提交到yarn或者mesos是分布式执行的,多个executor是运行在不同的机器上,统计结果要求写在一个指定的机器目录下。

思路

思路1:

是否可以将FTP发往下游的操作在spark应用程序中也一起实现了?
特殊场景可以,写一个spark的外部数据源,如下依赖可以做到,将DF的数据写到外部FTP,github连接如下
https://github.com/springml/spark-sftp

      
          com.springml
          spark-sftp_2.11
          1.1.3
      

但是对我不适用,因为我需要把DF写后的文件重命名为有业务意义的文件名


思路2:

将Spark streaming程序以local的方式运行,这样写的文件就是在本地了。数据量大的时候,还使用单机模式,显得很吃力,且不方便监控管理,local模式只是开发模式。


思路3:

先将DF的数据写到HDFS上,之后再用HDFS的copytoLocal命令拷贝到本地文件系统。
还需要避免拷贝后HDFS默认生成的CRC校验文件。


代码实现
 

重点在于如下代码:
 fileSystem.copyToLocalFile(true, files.getPath, new Path(s"$toLocalPath${dimension}_${preFile}_$batchTime.csv"), true)

  /**
   * @Description //TODO 将DF按照Csv的格式存储
   * @Date 17:42 2019/10/15 0015
   * @Param [dataFrame, dimension, batchTime, fileSystem]
   * @return void
   **/
  def saveFunc(dataFrame: DataFrame, dimension: String, batchTime: String, fileSystem: FileSystem) = {
    dataFrame.write.mode(SaveMode.Append)
      .partitionBy("sceneId")
      .option("compression", "none")
      .csv(s"$tmpPath/$dimension")
    //列出临时目录下的csv文件 移动
    val iterator = fileSystem.listFiles(new Path(s"$tmpPath/$dimension"), true)
    while (iterator.hasNext) {
      val files = iterator.next()
      val path = files.getPath
      if (files.isFile && path.getName.endsWith("csv")) {
        val preFile = path.getParent.getName.split("=")(1)
        fileSystem.copyToLocalFile(true, files.getPath, new Path(s"$toLocalPath${dimension}_${preFile}_$batchTime.csv"), true)
      }
    }
  }

 

你可能感兴趣的:(Spark)