2014-09-05 67 views
15

我在与使用这个简单的例子是“ClassNotFound的”异常的问题:火花提交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)) 
    } 
} 

在本地模式下,提交按照该文档生成上线31是“ClassNotFound的”异常, ClassToRoundTrip对象被反序列化。奇怪的是,第28行较早的使用是好的:

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

不过,如果我添加为“驱动程序类路径”额外的参数,和“-jars”,它工作正常,当地。

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文件正在被执行牵强看到。

日志用于执行程序的一个在这里:

标准输出:http://pastebin.com/raw.php?i=DQvvGhKm

标准错误:http://pastebin.com/raw.php?i=MPZZVa0Q

我使用星火1.0.2。 ClassToRoundTrip包含在JAR中。 我宁愿不必硬编码SPARK_CLASSPATH或SparkContext.addJar中的值。谁能帮忙?

+2

更新 - 我已经能够通过设置‘spark.executor.extraClassPath’,并作出解决此JAR文件在路径上的每个执行程序的本地可用。我不明白为什么需要这样做:JAR由执行程序从Spark的内部HTTP服务器提取并复制到每个执行程序的工作目录中。 – puppet 2014-09-08 14:37:52

+0

今天我看到同样的问题。 Jar正在被执行程序取回,并且它有类查找,即使它抛出ClassNotFoundException!我在1.0.2 btw – nir 2014-11-06 20:40:59

+0

再次更新 - 我认为这可能与序列化有关。几天前我们发现改变序列化方法使问题消失。我仍然不确定为什么,但值得一试。 – puppet 2014-11-08 19:46:37

回答

12

我有这个相同的问题。如果主人是本地人,那么程序对大多数人来说运行良好如果它们设置为(也发生在我身上)“spark:// myurl:7077”如果不起作用。大多数人都会遇到错误,因为在执行过程中没有找到匿名类。它通过使用SparkContext.addJars(“路径到jar”)来解决。

确保你正在做以下的事情: -

  • SparkContext.addJars( “路径从行家创建[提示:MVN包]罐子”)。
  • 我在代码中使用了SparkConf.setMaster(“spark:// myurl:7077”),并通过命令行提供了相同的参数。
  • 当您在命令行中指定类时,请确保您正在使用URL编写完整的名称。如:“packageName.ClassName”
  • 最后的命令应该是这样的 斌/火花提交--class “packageName.ClassName” --master 火花:// myurl:7077pathToYourJar /目标/yourJarFromMaven.jar

注:这个罐子pathToYourJar /目标/ yourJarFromMaven.jar在最后一点也是在代码中设置为这个答案的第一站。

+0

这个链接是无价的 - http://www.datastax.com/dev/blog/common-spark-troubleshooting;请注意,如果您不打算将依赖关系复制到所有节点,则需要包含'fat'jar。请点击此处查看如何使用sbt构建一个:assembly http://stackoverflow.com/questions/28459333/how-to-build-an-uber-jar-fat-jar-using-sbt-within-intellij-idea – 2016-06-13 12:03:44

3

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

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

This web page for trouble shooting也很有用。

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

然后它会工作。

0

如果您使用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>