it-swarm.com.de

Schreiben von Dateien in ein lokales System mit Spark im Cluster-Modus

Ich weiß, dass dies eine seltsame Art der Verwendung von Spark ist, aber ich versuche, ein Dataframe mithilfe von Spark im lokalen Dateisystem (nicht hdfs) zu speichern, obwohl ich in cluster mode bin. Ich weiß, dass ich client mode verwenden kann, aber ich möchte möchte in cluster mode ausgeführt werden, und es ist mir egal, auf welchem ​​Knoten (von 3) die Anwendung als Treiber ausgeführt wird . Der folgende Code ist der Pseudocode was ich versuche zu tun.

// 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")

Und so reiche ich den Funkenantrag ein.

spark-submit --class sample.HBaseSparkRSample --master yarn-cluster hbase-spark-r-sample-Assembly-1.0.jar

Dies funktioniert gut, wenn ich in local mode bin, aber nicht in yarn-cluster mode.

Beispielsweise tritt Java.io.IOException: Mkdirs failed to create file mit dem obigen Code auf.

Ich habe den df.coalesce(1)-Teil in df.collect geändert und versucht, eine Datei mit normalem Scala zu speichern, es wurde jedoch ein Permission denied ausgegeben.

Ich habe auch versucht:

  • spark-submit mit root Benutzer
  • chowned yarn:yarn, yarn:hadoop, spark:spark
  • chmod 777 zu verwandten Verzeichnissen gegeben

aber kein glück.

Ich gehe davon aus, dass dies etwas mit clusters, drivers and executors und der user zu tun hat, die versuchen, in das lokale Dateisystem zu schreiben, aber ich bin ziemlich fest damit beschäftigt, dieses Problem von mir selbst zu lösen.

Ich benutze:

  • Funke: 1.6.0-cdh5.8.2
  • Scala: 2.10.5
  • Hadoop: 2,6,0-cdh5,8,2

Jede Unterstützung ist willkommen und danke im Voraus.

Einige Artikel, die ich ausprobiert habe:

  • Msgstr "Spark saveAsTextFile () führt dazu, dass Mkdirs für die Hälfte des Verzeichnisses nicht erstellt werden konnte" -> Versuchte Benutzer zu ändern, aber nichts wurde geändert
  • Msgstr "RDD konnte nicht als Textdatei im lokalen Dateisystem gespeichert werden" -> chmod hat mir nicht geholfen

Bearbeitet (25.11.2016)

Dies ist die Ausnahme, die ich bekomme.

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)
12
tkrhgch

Ich werde meine eigene Frage beantworten, denn schließlich schien keine der Antworten mein Problem zu lösen. Trotzdem vielen Dank für all die Antworten und Hinweise auf Alternativen, die ich überprüfen kann.

Ich denke, @Ricardo hat den Benutzer der Spark-Anwendung am ehesten erwähnt. Ich habe whoami mit Process("whoami") überprüft und der Benutzer war yarn. Das Problem war wahrscheinlich, dass ich versucht habe, an /home/foo/work/rhbase/r/input/input.csv auszugeben. Obwohl /home/foo/work/rhbase von yarn:yarn besessen wurde, war /home/foo von foo:foo besessen. Ich habe nicht im Detail nachgesehen, aber dies könnte die Ursache dieses permission-Problems gewesen sein.

Wenn ich in meiner Spark-Anwendung mit Process("pwd") auf pwd tippe, wird /yarn/path/to/somewhere ausgegeben. Also entschied ich mich, meine Datei in /yarn/input.csv auszugeben und sie war trotz cluster mode erfolgreich.

Ich kann wahrscheinlich daraus schließen, dass dies nur eine einfache Berechtigungsfrage war. Jede weitere Lösung wäre willkommen, aber vorerst habe ich diese Frage auf diese Weise gelöst.

11
tkrhgch

Verwenden Sie die forEachPartition-Methode, und dann für jede Partition das Dateisystemobjekt abrufen und einen Datensatz nach dem anderen schreiben. Unten ist der Beispielcode. Hier schreibe ich in hdfs. Stattdessen können Sie auch das lokale Dateisystem verwenden

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();
        }
});
1
SanthoshPrasad

Wenn Sie den Job als yarn-cluster mode ausführen, wird der Treiber auf einem Computer ausgeführt, der von YARN verwaltet wird. Wenn saveAsTextFile über einen lokalen Dateipfad verfügt, speichert er die Ausgabe auf einem Computer, auf dem der Treiber ausgeführt wird. 

Versuchen Sie, den Job als yarn-client mode auszuführen, damit der Treiber auf dem Clientcomputer ausgeführt wird

1
Nirmal Ram

Prüfen Sie, ob Sie versuchen, die Datei mit einem anderen Benutzer als dem Spark-Dienst auszuführen/zu schreiben. In dieser Situation können Sie das Berechtigungsproblem lösen, indem Sie die Verzeichnis-ACLs vorgeben. Beispiel:

setfacl -d -m group:spark:rwx /path/to/

(Ändern Sie "spark" in Ihre Benutzergruppe, die versucht, die Datei zu schreiben.)

0
Ricardo

Informationen zur Verwendung der Option --master in spark-submit finden Sie in der Funken-Dokumentation.

  • --master local soll bei lokaler Ausführung verwendet werden.

  • --master yarn --deploy-mode cluster soll verwendet werden, wenn ein Garncluster tatsächlich ausgeführt wird.

das und das .

0
akaHuman