【发布时间】:2014-10-30 13:16:28
【问题描述】:
我在使用这个简单示例时遇到了“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
但是,如果我为“driver-class-path”和“-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
我使用的是 Spark 1.0.2。 ClassToRoundTrip 包含在 JAR 中。 我宁愿不必硬编码 SPARK_CLASSPATH 或 SparkContext.addJar 中的值。有人可以帮忙吗?
【问题讨论】:
-
更新 - 我已经能够通过设置“spark.executor.extraClassPath”并使 JAR 文件在路径上的每个执行程序上本地可用来解决这个问题。我不明白为什么需要这样做:JAR 正在由执行程序从 Spark 的内部 HTTP 服务器获取并复制到每个执行程序的工作目录中。
-
我今天看到了同样的问题。执行程序正在获取 Jar 并且它有它正在寻找的类,即使它抛出 ClassNotFoundException !我在 1.0.2 顺便说一句
-
再次更新——我认为这可能与序列化有关。几天前我们发现更改序列化方法可以解决问题。我仍然不确定为什么,但值得一试。
标签: scala jar classpath apache-spark