J'envoie un travail Spark à exécuter sur un cluster distant en exécutant
spark-submit ... --deploy-mode cluster --files some.properties ...
Je souhaite lire le contenu du fichier some.properties
à l’aide du driver code, c’est-à-dire avant de créer le contexte Spark et de lancer des tâches RDD. Le fichier est copié dans le pilote distant, mais pas dans le répertoire de travail du pilote.
Les manières de contourner ce problème que je connais sont:
Les deux sont gênants car ce fichier est fréquemment modifié sur la machine de développement en cours de soumission.
Existe-t-il un moyen de lire le fichier téléchargé à l'aide de l'indicateur --files
lors de la méthode principale du code de pilote?
Oui, vous pouvez accéder aux fichiers téléchargés via l'argument --files
.
Voici comment je peux accéder aux fichiers transmis via --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
et dans mon code Spark:
val filename = args(0)
val linecount = Source.fromFile(filename).getLines.size
Je pense que ces fichiers sont téléchargés sur les postes de travail dans le même répertoire que celui où le fichier jar a été placé. C’est pourquoi il suffit de passer le nom de fichier et non le chemin absolu vers Source.fromFile
.
Les options --files et --archives permettent de spécifier des noms de fichiers avec le # similaire à Hadoop. Par exemple, vous pouvez spécifier: --files localtest.txt # appSees.txt, ce qui téléchargera le fichier que vous avez nommé localement localtest.txt dans HDFS, mais sera lié au nom appSees.txt. Votre application doit utiliser le nommez appSees.txt pour le référencer lors de l'exécution sur YARN.
cela fonctionne pour mon application spark streaming en mode fil/client et en mode fil/cluster. peut peut-être vous aider
Après l’enquête, j’ai trouvé une solution au problème ci-dessus. Envoyez la configuration any.properties lors de l'étincelle d'envoi et utilisez-la à l'aide du pilote d'allumage avant et après l'initialisation de SparkSession. J'espère que cela vous aidera.
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:
spark-submit --class SparkTest --master yarn --deploy-mode client --files any.properties,yy-site.xml --jars ...........
utiliser spark-submit --help
, constatera que cette option concerne uniquement le répertoire de travail de l'exécuteur, pas le pilote.
--files FILES: Comma-separated list of files to be placed in the working directory of each executor.
Voici une solution intéressante que j'ai développée en Python Spark afin d'intégrer toutes les données sous forme de fichier de l'extérieur à votre plate-forme Big Data.
S'amuser.
# 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
Pour contourner le problème, vous pouvez créer une SparkContext
temporaire en appelant simplement SparkContext.getOrCreate()
, puis en lisant le fichier transmis dans le --files
à l'aide de SparkFiles.get('FILE')
.
Une fois que vous avez lu le fichier, récupérez toute la configuration nécessaire requise dans une variable SparkConf()
.
Après cet appel, cette fonction:
SparkContext.stop(SparkContext.getOrCreate())
Ceci distraira la SparkContext
existante et qu'à la ligne suivante, initialisera simplement une nouvelle SparkContext
avec les configurations nécessaires telles que celle-ci.
sc = SparkContext(conf=conf).getOrCreate()
Vous avez vous-même une SparkContext
avec les réglages souhaités