Je sais que c’est une façon étrange d’utiliser Spark, mais j’essaie de sauvegarder une base de données dans le système de fichiers local (et non en format hdfs) à l’aide de Spark, même si je suis dans cluster mode
. Je sais que je peux utiliser client mode
mais je fais veux exécuter cluster mode
et ne me soucie pas du nœud (sur 3) sur lequel l'application va s'exécuter en tant que pilote . Le code ci-dessous est le pseudo code de ce que j'essaie de faire.
// create dataframe
val df = Seq(Foo("John", "Doe"), Foo("Jane", "Doe")).toDF()
// save it to the local file system using 'file://' because it defaults to hdfs://
df.coalesce(1).rdd.saveAsTextFile(s"file://path/to/file")
Et voici comment je soumets la demande d'allumage.
spark-submit --class sample.HBaseSparkRSample --master yarn-cluster hbase-spark-r-sample-Assembly-1.0.jar
Cela fonctionne bien si je suis dans local mode
mais pas dans yarn-cluster mode
.
Par exemple, Java.io.IOException: Mkdirs failed to create file
apparaît avec le code ci-dessus.
J'ai changé la partie df.coalesce(1)
en df.collect
et j'ai essayé de sauvegarder un fichier en utilisant Scala mais cela s'est terminé par un Permission denied
.
J'ai aussi essayé:
spark-submit
avec root
utilisateurchown
ed yarn:yarn
, yarn:hadoop
, spark:spark
chmod 777
à des répertoires apparentésmais pas de chance.
Je suppose que cela doit faire quelque chose avec clusters
, drivers and executors
et le user
qui essaie d'écrire dans le système de fichiers local, mais je suis plutôt coincé dans la résolution de ce problème par moi-même.
J'utilise:
Tout support est le bienvenu et merci d’avance.
Quelques articles que j'ai essayés:
chmod
ne m'a pas aidéC'est l'exception que je reçois.
Java.io.IOException: Mkdirs failed to create file:/home/foo/work/rhbase/r/input/input.csv/_temporary/0/_temporary/attempt_201611242024_0000_m_000000_0 (exists=false, cwd=file:/yarn/nm/usercache/foo/appcache/application_1478068613528_0143/container_e87_1478068613528_0143_01_000001)
at org.Apache.hadoop.fs.ChecksumFileSystem.create(ChecksumFileSystem.Java:449)
at org.Apache.hadoop.fs.ChecksumFileSystem.create(ChecksumFileSystem.Java:435)
at org.Apache.hadoop.fs.FileSystem.create(FileSystem.Java:920)
at org.Apache.hadoop.fs.FileSystem.create(FileSystem.Java:813)
at org.Apache.hadoop.mapred.TextOutputFormat.getRecordWriter(TextOutputFormat.Java:135)
at org.Apache.spark.SparkHadoopWriter.open(SparkHadoopWriter.scala:91)
at org.Apache.spark.rdd.PairRDDFunctions$$anonfun$saveAsHadoopDataset$1$$anonfun$13.apply(PairRDDFunctions.scala:1193)
at org.Apache.spark.rdd.PairRDDFunctions$$anonfun$saveAsHadoopDataset$1$$anonfun$13.apply(PairRDDFunctions.scala:1185)
at org.Apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:66)
at org.Apache.spark.scheduler.Task.run(Task.scala:89)
at org.Apache.spark.executor.Executor$TaskRunner.run(Executor.scala:214)
at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1145)
at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:615)
at Java.lang.Thread.run(Thread.Java:745)
16/11/24 20:24:12 WARN scheduler.TaskSetManager: Lost task 0.0 in stage 0.0 (TID 0, localhost): Java.io.IOException: Mkdirs failed to create file:/home/foo/work/rhbase/r/input/input.csv/_temporary/0/_temporary/attempt_201611242024_0000_m_000000_0 (exists=false, cwd=file:/yarn/nm/usercache/foo/appcache/application_1478068613528_0143/container_e87_1478068613528_0143_01_000001)
at org.Apache.hadoop.fs.ChecksumFileSystem.create(ChecksumFileSystem.Java:449)
at org.Apache.hadoop.fs.ChecksumFileSystem.create(ChecksumFileSystem.Java:435)
at org.Apache.hadoop.fs.FileSystem.create(FileSystem.Java:920)
at org.Apache.hadoop.fs.FileSystem.create(FileSystem.Java:813)
at org.Apache.hadoop.mapred.TextOutputFormat.getRecordWriter(TextOutputFormat.Java:135)
at org.Apache.spark.SparkHadoopWriter.open(SparkHadoopWriter.scala:91)
at org.Apache.spark.rdd.PairRDDFunctions$$anonfun$saveAsHadoopDataset$1$$anonfun$13.apply(PairRDDFunctions.scala:1193)
at org.Apache.spark.rdd.PairRDDFunctions$$anonfun$saveAsHadoopDataset$1$$anonfun$13.apply(PairRDDFunctions.scala:1185)
at org.Apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:66)
at org.Apache.spark.scheduler.Task.run(Task.scala:89)
at org.Apache.spark.executor.Executor$TaskRunner.run(Executor.scala:214)
at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1145)
at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:615)
at Java.lang.Thread.run(Thread.Java:745)
Je vais répondre à ma propre question car, finalement, aucune des réponses ne semblait résoudre mon problème. Néanmoins, merci pour toutes les réponses et m'indiquer des alternatives que je peux vérifier.
Je pense que @Ricardo était le plus proche des utilisateurs de l'application Spark. J'ai vérifié whoami
avec Process("whoami")
et l'utilisateur était yarn
. Le problème était probablement que j'avais essayé de générer /home/foo/work/rhbase/r/input/input.csv
et que /home/foo/work/rhbase
appartenait à yarn:yarn
, /home/foo
appartenait à foo:foo
. Je n'ai pas vérifié en détail, mais c'est peut-être la cause de ce problème permission
.
Lorsque je clique sur pwd
dans mon application Spark avec Process("pwd")
, il génère /yarn/path/to/somewhere
. J'ai donc décidé de sortir mon fichier dans /yarn/input.csv
et le test a réussi malgré cluster mode
.
Je peux probablement conclure qu'il s'agissait simplement d'un simple problème d'autorisation. Toute autre solution serait la bienvenue, mais pour l’instant, c’est ainsi que j’ai résolu cette question.
Utilisez la méthode forEachPartition, puis pour chaque partition, récupérez un objet du système de fichiers et écrivez-y un enregistrement à la fois. Vous trouverez ci-dessous un exemple de code. Je vous écris sur hdfs.
Dataset<String> ds=....
ds.toJavaRdd.foreachPartition(new VoidFunction<Iterator<String>>() {
@Override
public void call(Iterator<String> iterator) throws Exception {
final FileSystem hdfsFileSystem = FileSystem.get(URI.create(finalOutPathLocation), hadoopConf);
final FSDataOutputStream fsDataOutPutStream = hdfsFileSystem.exists(finalOutPath)
? hdfsFileSystem.append(finalOutPath) : hdfsFileSystem.create(finalOutPath);
long processedRecCtr = 0;
long failedRecsCtr = 0;
while (iterator.hasNext()) {
try {
fsDataOutPutStream.writeUTF(iterator.next);
} catch (Exception e) {
failedRecsCtr++;
}
if (processedRecCtr % 3000 == 0) {
LOGGER.info("Flushing Records");
fsDataOutPutStream.flush();
}
}
fsDataOutPutStream.close();
}
});
Si vous exécutez le travail en tant que yarn-cluster mode
, le pilote sera exécuté sur l'un des ordinateurs gérés par YARN. Par conséquent, si saveAsTextFile
a un chemin d'accès au fichier local, il stockera la sortie sur l'un des ordinateurs sur lequel le pilote est exécuté.
Essayez d'exécuter le travail en tant que yarn-client mode
afin que le pilote s'exécute sur l'ordinateur client.
Vérifiez si vous essayez d'exécuter/d'écrire le fichier avec un utilisateur autre que le service Spark. Dans ce cas, vous pouvez résoudre le problème des autorisations en prédéfinissant les ACL du répertoire. Exemple:
setfacl -d -m group:spark:rwx /path/to/
(modifiez "spark" pour votre groupe d'utilisateurs essayant d'écrire le fichier)
Veuillez vous reporter à la documentation relative à spark pour comprendre l’utilisation de l’option --master
dans spark-submit
.
--master local
est censé être utilisé lors de l'exécution locale.
--master yarn --deploy-mode cluster
est censé être utilisé lors de l'exécution effective sur un cluster de fils.