Die häufigsten Probleme beim Erstellen und Bereitstellen von Spark-Anwendungen sind:
java.lang.ClassNotFoundException
.object x is not a member of package y
Kompilierungsfehler.java.lang.NoSuchMethodError
Wie können diese gelöst werden?
Benutzer7337271
Die häufigsten Probleme beim Erstellen und Bereitstellen von Spark-Anwendungen sind:
java.lang.ClassNotFoundException
.object x is not a member of package y
Kompilierungsfehler.java.lang.NoSuchMethodError
Wie können diese gelöst werden?
Tzach Zohar
Der Klassenpfad von Apache Spark wird dynamisch erstellt (um Benutzercode pro Anwendung aufzunehmen), was ihn für solche Probleme anfällig macht. Die Antwort von @ user7337271 ist richtig, aber je nach dem gibt es einige weitere Bedenken Cluster-Manager (“master”) Sie verwenden.
Erstens besteht eine Spark-Anwendung aus diesen Komponenten (jede ist eine separate JVM und enthält daher möglicherweise verschiedene Klassen in ihrem Klassenpfad):
SparkSession
(oder SparkContext
) und eine Verbindung zu einem Cluster-Manager herstellen, um die eigentliche Arbeit auszuführenDie Beziehung zwischen diesen wird in diesem Diagramm von Apache Spark beschrieben Übersicht über den Cluster-Modus:
Jetzt – Welche Klassen sollten sich in jeder dieser Komponenten befinden?
Dies kann durch das folgende Diagramm beantwortet werden:
Analysieren wir das langsam:
Spark-Code sind Sparks Bibliotheken. Sie sollten in existieren ALLE drei Komponenten, da sie den Klebstoff enthalten, mit dem Spark die Kommunikation zwischen ihnen durchführen kann. Übrigens – Spark-Autoren haben eine Designentscheidung getroffen, Code für ALLE Komponenten in ALLE Komponenten aufzunehmen (z. B. Code, der nur in Executor ausgeführt werden soll, auch in Treiber aufzunehmen), um dies zu vereinfachen – also Sparks „Fat Jar“ (in Versionen bis 1.6 ) oder “archive” (in 2.0, Details unten) enthalten den notwendigen Code für alle Komponenten und sollten in allen verfügbar sein.
Nur-Fahrer-Code Dies ist Benutzercode, der nichts enthält, was auf Executors verwendet werden sollte, dh Code, der in keiner Transformation auf dem RDD / DataFrame / Dataset verwendet wird. Dieser muss nicht unbedingt vom verteilten Benutzercode getrennt werden, kann es aber.
Verteilter Code Dies ist Benutzercode, der mit Treibercode kompiliert wird, aber auch auf den Executors ausgeführt werden muss – alles, was die eigentlichen Transformationen verwenden, muss in diesen JAR(s) enthalten sein.
Jetzt, wo wir das klargestellt haben, wie Lassen sich die Klassen in jeder Komponente korrekt laden, und welchen Regeln sollten sie folgen?
Spark-Code: Wie in früheren Antworten angegeben, müssen Sie dasselbe verwenden Skala und Funke Versionen in allen Komponenten.
1,1 Zoll Eigenständige -Modus gibt es eine „bereits vorhandene“ Spark-Installation, mit der sich Anwendungen (Treiber) verbinden können. Das bedeutet, dass alle Treiber müssen dieselbe Spark-Version verwenden läuft auf Master und Executoren.
1,2 Zoll GARN / Mesos, kann jede Anwendung eine andere Spark-Version verwenden, aber alle Komponenten derselben Anwendung müssen dieselbe Version verwenden. Das heißt, wenn Sie Version X zum Kompilieren und Packen Ihrer Treiberanwendung verwendet haben, sollten Sie beim Starten der SparkSession dieselbe Version bereitstellen (z spark.yarn.archive
oder spark.yarn.jars
Parameter bei Verwendung von YARN). Die von Ihnen bereitgestellten Gläser/Archive sollten alle Spark-Abhängigkeiten enthalten (einschließlich transitiver Abhängigkeiten) und wird vom Cluster-Manager an jeden Ausführenden gesendet, wenn die Anwendung gestartet wird.
Fahrercode: Das liegt ganz bei Ihnen – Treibercode kann als Bündel von Gläsern oder als “fettes Glas” versendet werden, solange es alle Spark-Abhängigkeiten + den gesamten Benutzercode enthält
Verteilter Code: Dieser Code muss nicht nur auf dem Treiber vorhanden sein, sondern auch an Ausführende gesendet werden (wiederum zusammen mit all seinen transitiven Abhängigkeiten). Dies geschieht mit der spark.jars
Parameter.
Zusammenfassenhier ist ein vorgeschlagener Ansatz zum Erstellen und Bereitstellen einer Spark-Anwendung (in diesem Fall mit YARN):
spark.jars
Parameter beim Starten der SparkSession
lib/
Ordner der heruntergeladenen Spark-Binärdateien als Wert von spark.yarn.archive
Benutzer7337271
Beim Erstellen und Bereitstellen von Spark-Anwendungen erfordern alle Abhängigkeiten kompatible Versionen.
Scala-Version. Alle Pakete müssen dieselbe Hauptversion (2.10, 2.11, 2.12) von Scala verwenden.
Betrachten Sie Folgendes (falsch) build.sbt
:
name := "Simple Project"
version := "1.0"
libraryDependencies ++= Seq(
"org.apache.spark" % "spark-core_2.11" % "2.0.1",
"org.apache.spark" % "spark-streaming_2.10" % "2.0.1",
"org.apache.bahir" % "spark-streaming-twitter_2.11" % "2.0.1"
)
Wir gebrauchen spark-streaming
für Scala 2.10, während die restlichen Pakete für Scala 2.11 sind. EIN gültig Datei sein könnte
name := "Simple Project"
version := "1.0"
libraryDependencies ++= Seq(
"org.apache.spark" % "spark-core_2.11" % "2.0.1",
"org.apache.spark" % "spark-streaming_2.11" % "2.0.1",
"org.apache.bahir" % "spark-streaming-twitter_2.11" % "2.0.1"
)
Es ist jedoch besser, die Version global anzugeben und zu verwenden %%
(was die Scala-Version für Sie anhängt):
name := "Simple Project"
version := "1.0"
scalaVersion := "2.11.7"
libraryDependencies ++= Seq(
"org.apache.spark" %% "spark-core" % "2.0.1",
"org.apache.spark" %% "spark-streaming" % "2.0.1",
"org.apache.bahir" %% "spark-streaming-twitter" % "2.0.1"
)
<project>
<groupId>com.example</groupId>
<artifactId>simple-project</artifactId>
<modelVersion>4.0.0</modelVersion>
<name>Simple Project</name>
<packaging>jar</packaging>
<version>1.0</version>
<properties>
<spark.version>2.0.1</spark.version>
</properties>
<dependencies>
<dependency> <!-- Spark dependency -->
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming_2.11</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.apache.bahir</groupId>
<artifactId>spark-streaming-twitter_2.11</artifactId>
<version>${spark.version}</version>
</dependency>
</dependencies>
</project>
Spark-Version Alle Pakete müssen dieselbe Hauptversion von Spark verwenden (1.6, 2.0, 2.1, …).
Betrachten Sie Folgendes (falsch) build.sbt:
name := "Simple Project"
version := "1.0"
libraryDependencies ++= Seq(
"org.apache.spark" % "spark-core_2.11" % "1.6.1",
"org.apache.spark" % "spark-streaming_2.10" % "2.0.1",
"org.apache.bahir" % "spark-streaming-twitter_2.11" % "2.0.1"
)
Wir gebrauchen spark-core
1.6, während die restlichen Komponenten in Spark 2.0 enthalten sind. EIN gültig Datei sein könnte
name := "Simple Project"
version := "1.0"
libraryDependencies ++= Seq(
"org.apache.spark" % "spark-core_2.11" % "2.0.1",
"org.apache.spark" % "spark-streaming_2.10" % "2.0.1",
"org.apache.bahir" % "spark-streaming-twitter_2.11" % "2.0.1"
)
aber es ist besser zu eine Variable verwenden
(immer noch falsch):
name := "Simple Project"
version := "1.0"
val sparkVersion = "2.0.1"
libraryDependencies ++= Seq(
"org.apache.spark" % "spark-core_2.11" % sparkVersion,
"org.apache.spark" % "spark-streaming_2.10" % sparkVersion,
"org.apache.bahir" % "spark-streaming-twitter_2.11" % sparkVersion
)
<project>
<groupId>com.example</groupId>
<artifactId>simple-project</artifactId>
<modelVersion>4.0.0</modelVersion>
<name>Simple Project</name>
<packaging>jar</packaging>
<version>1.0</version>
<properties>
<spark.version>2.0.1</spark.version>
<scala.version>2.11</scala.version>
</properties>
<dependencies>
<dependency> <!-- Spark dependency -->
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_${scala.version}</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming_${scala.version}</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.apache.bahir</groupId>
<artifactId>spark-streaming-twitter_${scala.version}</artifactId>
<version>${spark.version}</version>
</dependency>
</dependencies>
</project>
Die in Spark-Abhängigkeiten verwendete Spark-Version muss mit der Spark-Version der Spark-Installation übereinstimmen. Zum Beispiel Wenn Sie 1.6.1 auf dem Cluster verwenden, müssen Sie 1.6.1 zum Erstellen von Gläsern verwenden. Nicht übereinstimmende Nebenversionen werden nicht immer akzeptiert.
Die Scala-Version, die zum Erstellen von JAR verwendet wird, muss mit der Scala-Version übereinstimmen, die zum Erstellen von bereitgestelltem Spark verwendet wird. Standardmäßig (herunterladbare Binärdateien und Standard-Builds):
Zusätzliche Pakete sollten auf den Worker-Knoten zugänglich sein, wenn sie im Fat-Jar enthalten sind. Es gibt eine Reihe von Optionen, darunter:
--jars
Argument für spark-submit
– Lokal zu verteilen jar
Dateien.--packages
Argument für spark-submit
– um Abhängigkeiten aus dem Maven-Repository abzurufen.Bei der Einreichung im Cluster-Knoten sollten Sie die Bewerbung einschließen jar
in --jars
.
Winson
Zusätzlich zu der sehr ausführlichen Antwort, die bereits von user7337271 gegeben wurde, können Sie, wenn das Problem auf fehlende externe Abhängigkeiten zurückzuführen ist, ein Glas mit Ihren Abhängigkeiten mit zB erstellen Maven-Assembly-Plugin
Stellen Sie in diesem Fall sicher, dass alle Core-Spark-Abhängigkeiten in Ihrem Build-System als „bereitgestellt“ gekennzeichnet sind, und stellen Sie, wie bereits erwähnt, sicher, dass sie mit Ihrer Runtime-Spark-Version korrelieren.
Raymond Chen
Abhängigkeitsklassen Ihrer Anwendung sind in der anzugeben Anwendungsglas Option Ihres Startbefehls.
Weitere Einzelheiten finden Sie unter Spark-Dokumentation
Entnommen aus der Dokumentation:
application-jar: Pfad zu einem gebündelten JAR, das Ihre Anwendung und alle Abhängigkeiten enthält. Die URL muss innerhalb Ihres Clusters global sichtbar sein, z. B. ein hdfs://-Pfad oder ein file://-Pfad, der auf allen Knoten vorhanden ist
dmitrybugakov
Ich denke, dieses Problem muss ein Assembly-Plugin lösen. Du musst ein fettes Glas bauen. Zum Beispiel in sbt:
$PROJECT_ROOT/project/assembly.sbt
mit Code addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.0")
added some libraries
Bibliotheksabhängigkeiten ++= Seq(“com.some.company” %% “some-lib” % “1.0.0”)` Wenn Sie weitere Informationen benötigen, gehen Sie zu https://github.com/sbt/sbt-assembly
Manideep Karthik
Fügen Sie dem Projekt alle JAR-Dateien aus spark-2.4.0-bin-hadoop2.7\spark-2.4.0-bin-hadoop2.7\jars hinzu. Spark-2.4.0-bin-hadoop2.7 kann von heruntergeladen werden https://spark.apache.org/downloads.html
Sreerag
Ich habe die folgende build.sbt
lazy val root = (project in file(".")).
settings(
name := "spark-samples",
version := "1.0",
scalaVersion := "2.11.12",
mainClass in Compile := Some("StreamingExample")
)
libraryDependencies ++= Seq(
"org.apache.spark" %% "spark-core" % "2.4.0",
"org.apache.spark" %% "spark-streaming" % "2.4.0",
"org.apache.spark" %% "spark-sql" % "2.4.0",
"com.couchbase.client" %% "spark-connector" % "2.2.0"
)
// META-INF discarding
assemblyMergeStrategy in assembly := {
case PathList("META-INF", xs @ _*) => MergeStrategy.discard
case x => MergeStrategy.first
}
Ich habe ein dickes Glas meiner Anwendung mit dem sbt-Assembly-Plugin erstellt, aber wenn es mit spark-submit ausgeführt wird, schlägt es mit dem Fehler fehl:
java.lang.NoClassDefFoundError: rx/Completable$OnSubscribe
at com.couchbase.spark.connection.CouchbaseConnection.streamClient(CouchbaseConnection.scala:154)
Ich kann sehen, dass die Klasse in meinem Fettglas existiert:
jar tf target/scala-2.11/spark-samples-assembly-1.0.jar | grep 'Completable$OnSubscribe'
rx/Completable$OnSubscribe.class
Ich bin mir nicht sicher, was ich hier übersehe, irgendwelche Hinweise?
Ich hatte die Abhängigkeit com.couchbasespark-connector_2.11-2.2.0.jar manuell aus dem SBT-Cache ( .ivy2 ) in meine Spark-Installation kopiert, nach dem Entfernen funktionierte das Fat-Jar einwandfrei.
– Sreerag
27. Februar 2019 um 7:07 Uhr
Normalerweise treten diese Fehler auf, weil Ihre Anwendung nicht richtig gebündelt ist. Wenn ich an etwas in Maven oder SBT arbeite, wird normalerweise die Ausgabe von analysiert
jar tf jar-file
die die Klassen in einem Glas druckt.– Myles Baker
10. Januar 2017 um 0:03 Uhr
Sehr gut formulierte Frage! Hut ab! (Umfasst eine Vielzahl von Problemen, die eine gemeinsame Ursache haben.)
– Marco
5. Februar 2019 um 10:39 Uhr