2014-09-05 14 views
15

Sto avendo problemi con un'eccezione "ClassNotFound" con questo semplice esempio:Spark-presentare eccezione ClassNotFound

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)) 
    } 
} 

In modalità locale, presentando come per i documenti genera un'eccezione "ClassNotFound" sulla linea 31, dove l'oggetto ClassToRoundTrip è deserializzato. Stranamente, l'uso in precedenza sulla linea 28 va bene:

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

Tuttavia, se aggiungo i parametri aggiuntivi per "conducente-class-path" e "-jars", funziona benissimo, il locale.

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 

Tuttavia, la presentazione di un maestro locale dev, genera sempre lo stesso problema:

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 

posso vedere dall'output che il file JAR è essere recuperato dal l'esecutore.

registri per uno dei esecutore di qui:

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

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

sto usando Spark 1.0.2. ClassToRoundTrip è incluso nel JAR. Preferirei non avere valori hardcode in SPARK_CLASSPATH o SparkContext.addJar. Qualcuno può aiutare?

+2

Aggiornamento - Sono stato in grado di ovviare a questo impostando il 'spark.executor.extraClassPath' e rendendo la File JAR localmente disponibile su ciascun esecutore nel percorso. Non capisco perché sia ​​necessario: il JAR viene prelevato dal server HTTP interno di Spark dall'esecutore e copiato nella directory di lavoro di ciascun esecutore. – puppet

+0

Oggi vedo lo stesso problema. Jar è stato scaricato dall'esecutore e ha la classe che sta cercando anche se lancia ClassNotFoundException !! Sono su 1.0.2 btw – nir

+0

Aggiornamento di nuovo - Penso che questo potrebbe avere qualcosa a che fare con la serializzazione. Abbiamo scoperto un paio di giorni fa che la modifica del metodo di serializzazione ha risolto il problema. Non sono ancora sicuro del perché, ma vale la pena provare. – puppet

risposta

12

Ho avuto lo stesso problema. Se il master è locale, il programma funziona correttamente per la maggior parte delle persone. Se lo impostano (anche a me) "spark: // myurl: 7077" se non funziona. La maggior parte delle persone riceve un errore perché non è stata trovata una classe anonima durante l'esecuzione. È stato risolto utilizzando SparkContext.addJars ("Path to jar").

Assicurarsi che si sta facendo le cose seguenti: -

  • SparkContext.addJars ("Path to vaso creato da Maven [suggerimento: pacchetto mvn]").
  • Ho usato SparkConf.setMaster ("spark: // myurl: 7077") nel codice e ho fornito lo stesso argomento durante l'invio del lavoro a spark tramite la riga di comando.
  • Quando si specifica la classe nella riga di comando, assicurarsi che si stia scrivendo il nome completo con l'URL. ad esempio: "packageName.ClassName"
  • comando finale dovrebbe assomigliare a questa bin/scintilla presentare --class "packageName.ClassName" --master scintilla: // myurl: 7077pathToYourJar/target /yourJarFromMaven.jar

Nota: questo barattolo pathToYourJar/target/yourJarFromMaven.jar in ultimo punto viene impostato anche in codice come primo punto di questa risposta.

+0

Questo link è inestimabile - http://www.datastax.com/dev/blog/common-spark-troubleshooting; Si noti che è necessario includere un jar "grasso" se non si prevede di copiare le dipendenze su tutti i nodi. Si prega di controllare qui per vedere come costruirne uno usando sbt: assembly http://stackoverflow.com/questions/28459333/how-to-build-an-uber-jar-fat-jar-using-sbt-within-intellij-idea –

3

Ho anche avuto lo stesso problema. Penso che --jars non stia spedendo i vasi agli esecutori. Dopo averlo aggiunto a SparkConf, funziona perfettamente.

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

This web page for trouble shooting è anche utile.

3

È necessario impostare la SPARK_CLASS_PATH in spark-env.sh file di come questo:

SPARK_LOCAL_IP=your local ip 
SPARK_CLASSPATH=your external jars 

e si dovrebbe presentare con le coperture scintilla in questo modo: spark-submit --class your.runclass --master spark://yourSparkMasterHostname:7077 /your.jar

e il codice Java in questo modo:

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

quindi funzionerà.

0

Se si utilizza il plug-in Maven e Maven Assembly per creare il file jar con mvn package, assicurarsi che il plug-in dell'assembly sia configurato correttamente in modo che punti alla classe principale dell'app Spark.

Qualcosa del genere dovrebbe essere aggiunto al vostro pom.xml per evitare eventuali 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>