Spark-submit ClassNotFound异常

时间:2014-09-05 14:36:32

标签: scala jar classpath apache-spark

我遇到了#34; 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))
  }
}

在本地模式下,按照文档提交会生成一个&#34; ClassNotFound&#34;第31行的异常,其中ClassToRoundTrip对象被反序列化。奇怪的是,第28行的早期使用是可以的:

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

但是,如果我为&#34; driver-class-path&#34;和&#34; -jars&#34;添加额外的参数,它在本地工作正常。

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

但是,提交给本地开发大师仍然会产生同样的问题:

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

我可以从输出中看到执行程序正在获取JAR文件。

其中一位遗嘱执行人的日志在这里:

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

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

我使用的是Spark 1.0.2。 ClassToRoundTrip包含在JAR中。 我宁愿不必在SPARK_CLASSPATH或SparkContext.addJar中硬编码值。有人可以帮忙吗?

5 个答案:

答案 0 :(得分:15)

我有同样的问题。如果master是本地的,那么程序对大多数人来说运行良好。如果他们把它设置为(也发生在我身上)&#34; spark:// myurl:7077&#34;如果不起作用。大多数人都会收到错误,因为在执行过程中找不到匿名类。它通过使用SparkContext.addJars(&#34; jar to jar&#34;)来解决。

确保您正在执行以下操作: -

  • SparkContext.addJars(&#34; 从maven创建jar的路径[hint:mvn package] &#34;)。
  • 我在代码中使用了SparkConf.setMaster(&#34; spark:// myurl:7077 &#34;)并在通过命令行提交作业时提供了相同的参数。
  • 在命令行中指定class时,请确保使用URL编写完整的名称。例如:&#34; packageName.ClassName&#34;
  • 最终命令应如下所示 bin / spark-submit --class &#34; packageName.ClassName&#34; --master spark:// myurl:7077 pathToYourJar / target / yourJarFromMaven的.jar

注意:此jar路径最后一点的toTourYarJar / target / yourJarFromMaven.jar也在代码中设置,如此答案的第一点。

答案 1 :(得分:3)

我也有同样的问题。我认为--jars不会将罐装运送给执行者。 将此添加到SparkConf后,它可以正常工作。

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

This web page for trouble shooting也很有用。

答案 2 :(得分:3)

您应该在 spark-env.sh 文件中设置SPARK_CLASS_PATH,如下所示:

SPARK_LOCAL_IP=your local ip 
SPARK_CLASSPATH=your external jars

你应该像这样提交火花外壳:spark-submit --class your.runclass --master spark://yourSparkMasterHostname:7077 /your.jar

和你的java代码一样:

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

然后它会起作用。

答案 3 :(得分:1)

如果您使用Maven和Maven Assembly插件使用mvn package构建jar文件,请确保正确配置程序集插件以指向Spark应用程序的主类。

应该将这样的内容添加到您的pom.xml中,以避免任何java.lang.ClassNotFoundException

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

答案 4 :(得分:0)

我发现,如果您在没有任何警告的情况下构建项目,那么您就不必为master和其他内容编写额外的代码。虽然这是一个好习惯,但是您可以避免它。就像这里的情况一样,项目中没有警告,因此我能够在不使用任何额外代码的情况下运行它。 Project Structure Link

在我有一些与构建相关的警告的情况下,我必须照顾JAR路径,我的URL和代码中的母版以及在执行时。

我希望它可以帮助某人。干杯!