2014-09-05 26 views
15

Mam problemy z „ClassNotFound” wyjątek przy użyciu tego prostego przykładu:Spark-submit ClassNotFound wyjątek

import org.apache.spark.SparkContext 
import org.apache.spark.SparkContext._ 
import org.apache.spark.SparkConf 

import java.net.URLClassLoader 

import scala.util.Marshal 

class ClassToRoundTrip(val id: Int) extends scala.Serializable { 
} 

object RoundTripTester { 

    def test(id : Int) : ClassToRoundTrip = { 

    // Get the current classpath and output. Can we see simpleapp jar? 
    val cl = ClassLoader.getSystemClassLoader 
    val urls = cl.asInstanceOf[URLClassLoader].getURLs 
    urls.foreach(url => println("Executor classpath is:" + url.getFile)) 

    // Simply instantiating an instance of object and using it works fine. 
    val testObj = new ClassToRoundTrip(id) 
    println("testObj.id: " + testObj.id) 

    val testObjBytes = Marshal.dump(testObj) 
    val testObjRoundTrip = Marshal.load[ClassToRoundTrip](testObjBytes) // <<-- ClassNotFoundException here 
    testObjRoundTrip 
    } 
} 

object SimpleApp { 
    def main(args: Array[String]) { 

    val conf = new SparkConf().setAppName("Simple Application") 
    val sc = new SparkContext(conf) 

    val cl = ClassLoader.getSystemClassLoader 
    val urls = cl.asInstanceOf[URLClassLoader].getURLs 
    urls.foreach(url => println("Driver classpath is: " + url.getFile)) 

    val data = Array(1, 2, 3, 4, 5) 
    val distData = sc.parallelize(data) 
    distData.foreach(x=> RoundTripTester.test(x)) 
    } 
} 

W trybie lokalnym, składając zgodnie docs generuje „ClassNotFound” wyjątek na linii 31, gdzie obiekt ClassToRoundTrip jest deserialized. Co dziwne, wcześniej zastosowanie na linii 28 jest w porządku:

spark-submit --class "SimpleApp" \ 
      --master local[4] \ 
      target/scala-2.10/simpleapp_2.10-1.0.jar 

Jednak jeśli dodać dodatkowe parametry dla „kierowca klasy ścieżce” i „-jars”, to działa dobrze, na poziomie lokalnym.

spark-submit --class "SimpleApp" \ 
      --master local[4] \ 
      --driver-class-path /home/xxxxxxx/workspace/SimpleApp/target/scala-2.10/simpleapp_2.10-1.0.jar \ 
      --jars /home/xxxxxxx/workspace/SimpleApp/target/scala-2.10/SimpleApp.jar \ 
      target/scala-2.10/simpleapp_2.10-1.0.jar 

jednak złożenie do lokalnego mistrza dev, wciąż generuje ten sam problem:

spark-submit --class "SimpleApp" \ 
      --master spark://localhost.localdomain:7077 \ 
      --driver-class-path /home/xxxxxxx/workspace/SimpleApp/target/scala-2.10/simpleapp_2.10-1.0.jar \ 
      --jars /home/xxxxxxx/workspace/SimpleApp/target/scala-2.10/simpleapp_2.10-1.0.jar \ 
      target/scala-2.10/simpleapp_2.10-1.0.jar 

widzę z wyjścia, że ​​plik JAR jest będącego pobierane przez Wykonawcę.

Logi do jednego z wykonawcą są tutaj:

stdout: http://pastebin.com/raw.php?i=DQvvGhKm

stderr: http://pastebin.com/raw.php?i=MPZZVa0Q

Używam Spark 1.0.2. ClassToRoundTrip jest zawarty w JAR. Wolałbym nie mieć wartości hardcode w SPARK_CLASSPATH lub SparkContext.addJar. Czy ktoś może pomóc?

+2

Aktualizacja - udało mi się obejść to przez ustawienie«spark.executor.extraClassPath»i czyniąc Plik JAR lokalnie dostępny na każdym executorze znajdującym się na ścieżce. Nie rozumiem, dlaczego jest to potrzebne: JAR jest pobierany z wewnętrznego serwera HTTP Sparka przez executor i kopiowany do katalogu roboczego każdego executora. – puppet

+0

Dzisiaj widzę ten sam problem. Słoik jest pobierany przez executora i ma klasę, której szuka, mimo że generuje wyjątek ClassNotFoundException !! Jestem na 1.0.2 btw – nir

+0

Zaktualizuj ponownie - Myślę, że to może mieć coś wspólnego z serializacją. Znaleźliśmy kilka dni temu, że zmiana metody serializacji sprawiła, że ​​problem zniknął. Wciąż nie jestem pewien dlaczego, ale warto spróbować. – puppet

Odpowiedz

12

Miałem ten sam problem. Jeśli master jest lokalny, program działa dobrze dla większości ludzi. Jeśli ustawią to (również mi się przydarzyło) "spark: // myurl: 7077", jeśli nie działa. Większość ludzi otrzymuje błąd, ponieważ podczas wykonywania nie znaleziono anonimowej klasy. Jest to rozwiązywane za pomocą SparkContext.addJars ("Ścieżka do słoika").

Upewnij robisz następujące rzeczy: -

  • SparkContext.addJars ("Ścieżka do słoika utworzonego z Maven [podpowiedź: pakiet mvn]").
  • Użyłem SparkConf.setMaster ("iskra: // myurl: 7077") w kodzie i dostarczyłem ten sam argument podczas przesyłania zadania do iskry za pośrednictwem wiersza poleceń.
  • Po określeniu klasy w wierszu poleceń, upewnij się, że wpisujesz pełną nazwę z adresem URL. np: "packageName.ClassName"
  • komenda końcowy powinien wyglądać ten bin/iskra przesłać --class "packageName.ClassName" --master iskry: // myurl: 7077pathToYourJar/docelowej /yourJarFromMaven.jar

Uwaga: ten słoik pathToYourJar/target/yourJarFromMaven.jar w ostatnim punkcie jest również ustawić w kodzie jak w pierwszym punkcie tej odpowiedzi.

+0

Ten link jest nieoceniony - http://www.datastax.com/dev/blog/common-spark-troubleshooting; Zauważ, że musisz dołączyć "gruby" jar, jeśli nie planujesz kopiować zależności do wszystkich węzłów. Proszę sprawdzić tutaj, jak zbudować jedną przy użyciu sbt: assembly http://stackoverflow.com/questions/28459333/how-to-build-an-uber-jar-fat-jar-using-sbt-within-intellij-idea –

3

Też miałem ten sam problem. Myślę, że - jars nie wysyła słoików do executorów. Po dodaniu tego do SparkConf działa dobrze.

val conf = new SparkConf().setMaster("...").setJars(Seq("https://stackoverflow.com/a/b/x.jar", "/c/d/y.jar")) 

This web page for trouble shooting też jest przydatne.

3

Należy ustawić SPARK_CLASS_PATH w spark-env.sh pliku takiego:

SPARK_LOCAL_IP=your local ip 
SPARK_CLASSPATH=your external jars 

i należy złożyć z powłoką iskrowym jak to: spark-submit --class your.runclass --master spark://yourSparkMasterHostname:7077 /your.jar

i kodu Java tak:

SparkConf sparkconf = new SparkConf().setAppName("sparkOnHbase"); JavaSparkContext sc = new JavaSparkContext(sparkconf); 

to zadziała.

0

Jeśli używasz Maven i Maven Assembly wtyczki zbudować plik jar z mvn package upewnić się, że wtyczka jest prawidłowo skonfigurowany montaż pkt do głównej klasy twojego zapłonową aplikacji.

Coś jak to powinno być dodany do pom.xml aby uniknąć wszelkich java.lang.ClassNotFoundException „s:

  <plugin> 
      <groupId>org.apache.maven.plugins</groupId> 
      <artifactId>maven-assembly-plugin</artifactId> 
      <version>2.4.1</version> 
      <configuration> 
       <archive> 
        <manifest> 
         <mainClass>com.my.package.SparkDriverApp</mainClass> 
        </manifest> 
       </archive> 
       <descriptorRefs> 
        <descriptorRef>jar-with-dependencies</descriptorRef> 
       </descriptorRefs> 
       <skipAssembly>false</skipAssembly> 
      </configuration> 
      <executions> 
       <execution> 
        <id>package</id> 
        <phase>package</phase> 
        <goals> 
         <goal>single</goal> 
        </goals> 
       </execution> 
      </executions> 
     </plugin>