Spark yarn-cluster模式 - 使用--files传递的读取文件

时间:2015-11-20 15:57:23

标签: hadoop apache-spark hdfs yarn

我正在使用yarn-cluster master运行我的spark应用程序。

应用程序做了什么?

  1. 外部服务根据对RESTService的HTTP请求生成jsonFile
  2. Spark需要读取此文件并在解析json后执行一些工作
  3. 最简单的解决方案是使用--files来加载该文件。 在纱线群集模式下读取文件意味着它必须在hdfs上可用(如果我对吗?)并且我的文件被复制到这样的路径:

    /hadoop_user_path/.sparkStaging/spark_applicationId/myFile.json
    

    我当然可以阅读它,但我找不到从任何配置/ SparkEnv对象获取此路径的方法。并且在火花代码中使用硬编码.sparkStaging就像一个坏主意一样。

    为什么简单:

    val jsonStringData = spark.textFile(myFileName)
    sqlContext.read.json(jsonStringData)
    

    无法读取--files传递的文件并抛出FileNotFoundException?为什么spark只在hadoop_user_folder中查找文件?

    我现在有效的解决方案:

    在运行spark之前,我将文件复制到正确的hdfs文件夹,将文件名作为Spark参数传递,从已知路径处理文件,并在作业完成后删除文件格式hdfs。

    我认为将文件传递为--files会让我忘记保存和删除此文件。类似于pass-process-andforget。

    你如何读取--files传递的文件呢?唯一的解决方案是手工创建路径,硬编码" .sparkStaging"文件夹路径?

4 个答案:

答案 0 :(得分:2)

这个问题写得很模糊。但是,从我看来,您希望从本地操作系统文件系统的任何位置读取文件,而不仅仅是从HDFS读取文件。

Spark使用URI来标识路径,并且在有效的Hadoop / HDFS环境的可用性中,它将默认为HDFS。在这种情况下,要指向本地OS文件系统,例如UNIX / LINUX,您可以使用以下内容:

file:///home/user/my_file.txt

如果您使用RDD从此文件中读取,您以纱线群集模式运行,或者在任务中访问该文件,则需要手动将该文件复制并分发到您的所有节点中集群,使用相同的路径。这就是它首先将它放在hfs上的简单方法,或者--files选项应该为你做的事情。

查看有关Spark, External Datasets的更多信息。

对于通过--files选项添加或通过SparkContext.addFile添加的任何文件,您可以使用SparkFiles帮助程序类获取有关其位置的信息。

答案 1 :(得分:1)

来自@hartar的回答为我工作。这是完整的解决方案。

使用--files

在spark-submit期间添加所需文件
spark-submit --name "my_job" --master yarn --deploy-mode cluster --files /home/xyz/file1.properties,/home/xyz/file2.properties --class test.main /home/xyz/my_test_jar.jar

在main方法中获取spark会话

SparkSession ss = new SparkSession.Builder().getOrCreate();

由于我只对.properties文件感兴趣,我正在过滤它,相反,如果你知道你想要读取的文件名,那么它可以直接在FileInputStream中使用。

spark.yarn.dist.files将它存储为文件:/home/xyz/file1.properties,file:/home/xyz/file2.properties因此将字符串拆分为(,)和(/),以便我可以删除除文件名以外的其他内容。

String[] files = Pattern.compile("/|,").splitAsStream(ss.conf().get("spark.yarn.dist.files")).filter(s -> s.contains(".properties")).toArray(String[]::new);

//load all files to Property                
for (String f : files) {
    props.load(new FileInputStream(f));
}

答案 2 :(得分:0)

我遇到了和你一样的问题,事实上,你必须知道,当你发送一个可执行文件和文件时,它们处于同一级别,所以在你的可执行文件中,只需将文件名放到Access即可因为你的可执行文件是基于它自己的文件夹。

您不需要使用sparkFiles或任何其他类。只是像readFile(“myFile.json”);

这样的方法

答案 3 :(得分:0)

我遇到了一种简单的方法。 我们在伪分布模式下的纱线上使用Spark 2.3.0。我们需要从spark查询一个postgres表,其配置在属性文件中定义。 我使用spark提交的--files属性传递了属性文件。要在我的代码中读取文件,我只使用了java.util.Properties.PropertiesReader类。

我只需要确保加载文件时指定的路径与--files参数中传递的路径相同

例如如果spark提交命令如下所示:     spark-submit --class --master yarn --deploy-mode client-files test / metadata.properties myjar.jar

然后我读取文件的代码将如下所示: 属性props = new Properties(); props.load(new FileInputStream(new File(“ test / metadata.properties”))))

希望这对您有所帮助。