Spark-soumettre ClassNotFound exception

Je vais avoir des problèmes avec un "ClassNotFound" Exception à l'aide de cet exemple simple:

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

En mode local, la soumission conformément à la documentation génère un "ClassNotFound" exception à la ligne 31, où le ClassToRoundTrip objet désérialisé. Étrangement, l'utilisation antérieure sur la ligne 28 est d'accord:

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

Cependant, si j'ai ajouter des paramètres supplémentaires pour "driver-class-path", et "-pots", il fonctionne très bien, sur le local.

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

Toutefois, la soumission à un local dev master, génère toujours la même question:

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

Je peux voir à partir de la sortie que le fichier JAR est récupérée par l'exécuteur testamentaire.

Journaux pour l'un de l'exécuteur êtes ici:

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

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

Je suis en utilisant Étincelle 1.0.2. Le ClassToRoundTrip est inclus dans le POT.
Je préfère ne pas avoir à coder en dur des valeurs dans SPARK_CLASSPATH ou SparkContext.addJar. Quelqu'un peut-il aider?

Mise à jour - j'ai été en mesure de contourner ce problème en définissant le "étincelle.exécuteur testamentaire.extraClassPath" et le fichier JAR disponible localement sur chacun de l'exécuteur dans le chemin. Je ne comprends pas pourquoi c'est nécessaire: Le POT est récupérée à partir de l'Étincelle interne du serveur HTTP par l'exécuteur et copié dans le répertoire de travail de chaque interprète.
Je vois le même problème aujourd'hui. Jar est récupérée par l'exécuteur testamentaire et il a la classe de sa recherche, même si elle jette ClassNotFoundException!! Je suis sur la version 1.0.2 btw
Mise à jour - je crois que cela pourrait avoir quelque chose à voir avec la sérialisation. Nous avons trouvé il y a quelques jours que la modification de la méthode de sérialisation fait le problème. Je ne sais pas encore pourquoi, mais il vaut la peine d'essayer.

OriginalL'auteur puppet | 2014-09-05