我发送一个Spark作业,通过运行
在远程集群上运行spark-submit ... --deploy-mode cluster --files some.properties ...
我想通过驱动程序代码读取some.properties
文件的内容,即在创建Spark上下文和启动RDD任务之前。该文件将复制到远程驱动程序,但不会复制到驱动程序的工作目录。
我所知道的解决这个问题的方法是:
两者都不方便,因为在提交开发机器上经常更改此文件。
有没有办法在驱动程序代码main方法中读取使用--files
标志上传的文件?
答案 0 :(得分:19)
是的,您可以访问通过--files
参数上传的文件。
这就是我能够访问通过--files
传入的文件的方式:
./bin/spark-submit \
--class com.MyClass \
--master yarn-cluster \
--files /path/to/some/file.ext \
--jars lib/datanucleus-api-jdo-3.2.6.jar,lib/datanucleus-rdbms-3.2.9.jar,lib/datanucleus-core-3.2.10.jar \
/path/to/app.jar file.ext
并在我的Spark代码中:
val filename = args(0)
val linecount = Source.fromFile(filename).getLines.size
我相信这些文件会被下载到放置jar的同一目录中的worker上,这就是为什么只是传递文件名而不是Source.fromFile
的绝对路径。
答案 1 :(得分:4)
经过调查,我找到了解决上述问题的一种方法。在Spark提交期间发送 any.properties 配置,并在SparkSession初始化之前和之后由Spark驱动程序使用。希望对您有帮助。
any.properties
spark.key=value
spark.app.name=MyApp
SparkTest.java
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
public class SparkTest{
public Static void main(String[] args){
String warehouseLocation = new File("spark-warehouse").getAbsolutePath();
Config conf = loadConf();
System.out.println(conf.getString("spark.key"));
// Initialize SparkContext and use configuration from properties
SparkConf sparkConf = new SparkConf(true).setAppName(conf.getString("spark.app.name"));
SparkSession sparkSession =
SparkSession.builder().config(sparkConf).config("spark.sql.warehouse.dir", warehouseLocation)
.enableHiveSupport().getOrCreate();
JavaSparkContext javaSparkContext = new JavaSparkContext(sparkSession.sparkContext());
}
public static Config loadConf() {
String configFileName = "any.properties";
System.out.println(configFileName);
Config configs = ConfigFactory.load(ConfigFactory.parseFile(new java.io.File(configFileName)));
System.out.println(configs.getString("spark.key")); // get value from properties file
return configs;
}
}
火花提交:
spark-submit --class SparkTest --master yarn --deploy-mode client --files any.properties,yy-site.xml --jars ...........
答案 2 :(得分:2)
--files和--archives选项支持使用与Hadoop类似的#指定文件名。例如,您可以指定:--files localtest.txt#appSees.txt,这会将您在本地命名为localtest.txt的文件上传到HDFS,但这将通过名称appSees.txt链接,您的应用程序应使用命名为appSees.txt,以便在YARN上运行时引用它。
这适用于纱线/客户端和纱线/群集模式下的火花流应用。也许可以帮到你
答案 3 :(得分:0)
这是我在Python Spark中开发的一个很好的解决方案,可以将任何数据作为文件从外部集成到大数据平台。
玩得开心。
# Load from the Spark driver any local text file and return a RDD (really useful in YARN mode to integrate new data at the fly)
# (See https://community.hortonworks.com/questions/38482/loading-local-file-to-apache-spark.html)
def parallelizeTextFileToRDD(sparkContext, localTextFilePath, splitChar):
localTextFilePath = localTextFilePath.strip(' ')
if (localTextFilePath.startswith("file://")):
localTextFilePath = localTextFilePath[7:]
import subprocess
dataBytes = subprocess.check_output("cat " + localTextFilePath, shell=True)
textRDD = sparkContext.parallelize(dataBytes.split(splitChar))
return textRDD
# Usage example
myRDD = parallelizeTextFileToRDD(sc, '~/myTextFile.txt', '\n') # Load my local file as a RDD
myRDD.saveAsTextFile('/user/foo/myTextFile') # Store my data to HDFS
答案 4 :(得分:0)
解决问题的方法是,只需调用SparkContext
即可创建临时SparkContext.getOrCreate()
,然后在--files
的帮助下阅读SparkFiles.get('FILE')
中传递的文件}。
阅读文件后,检索SparkConf()
变量中所需的所有必要配置。
之后调用此函数:
SparkContext.stop(SparkContext.getOrCreate())
这将破坏现有的SparkContext
,而不是在下一行中使用必要的配置来初始化新的SparkContext
。
sc = SparkContext(conf=conf).getOrCreate()
您自己拥有所需设置的SparkContext
答案 5 :(得分:0)
使用spark-submit --help
,将发现此选项仅适用于执行程序的工作目录而不是驱动程序。
--files FILES: Comma-separated list of files to be placed in the working directory of each executor.
答案 6 :(得分:0)
在pyspark中,我发现轻松实现这一目标真的很有趣,首先要安排您的工作目录,如下所示:
/path/to/your/workdir/
|--code.py
|--file.txt
,然后在您的code.py主函数中,照常读取文件:
if __name__ == "__main__":
content = open("./file.txt").read()
然后提交,无需进行以下任何特定配置:
spark-submit code.py
它运行正常,这让我感到惊讶。我想提交过程将所有文件和子目录文件全部存档,然后将它们发送到pyspark中的驱动程序,而您应该自己在scala版本中存档它们。顺便说一句,-files和--archives选项都在工作程序中而不是在驱动程序中工作,这意味着您只能在RDD转换或操作中访问这些文件。