【问题标题】:Spark custom serializer leads to ClassNotFoundSpark 自定义序列化程序导致 ClassNotFound
【发布时间】:2016-04-11 12:41:56
【问题描述】:

我正在尝试使用 custom spark serializer 定义为:

conf.set("spark.serializer", CustomSparkSerializer.class.getCanonicalName());

但是当我向 Spark 提交应用程序时,我在创建执行程序 env 时遇到了 ClassNotFoundException 问题,例如:

16/04/01 18:41:11 INFO util.Utils:在端口 52153 上成功启动服务“sparkExecutor”。

Exception in thread "main" java.lang.reflect.UndeclaredThrowableException
        at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1643)
        at org.apache.spark.deploy.SparkHadoopUtil.runAsSparkUser(SparkHadoopUtil.scala:68)
        at org.apache.spark.executor.CoarseGrainedExecutorBackend$.run(CoarseGrainedExecutorBackend.scala:149)
        at org.apache.spark.executor.CoarseGrainedExecutorBackend$.main(CoarseGrainedExecutorBackend.scala:250)
        at org.apache.spark.executor.CoarseGrainedExecutorBackend.main(CoarseGrainedExecutorBackend.scala)
Caused by: java.lang.ClassNotFoundException: example.CustomSparkSerializer
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:270)
        at **org.apache.spark.util.Utils$.classForName(Utils.scala:173)**
        at org.apache.spark.SparkEnv$.instantiateClass$1(SparkEnv.scala:266)
        at org.apache.spark.SparkEnv$.instantiateClassFromConf$1(SparkEnv.scala:287)
        at org.apache.spark.SparkEnv$.create(SparkEnv.scala:290)
        at org.apache.spark.SparkEnv$.createExecutorEnv(SparkEnv.scala:218)
        at org.apache.spark.executor.CoarseGrainedExecutorBackend$$anonfun$run$1.apply$mcV$sp(CoarseGrainedExecutorBackend.scala:183)
        at org.apache.spark.deploy.SparkHadoopUtil$$anon$1.run(SparkHadoopUtil.scala:69)
        at org.apache.spark.deploy.SparkHadoopUtil$$anon$1.run(SparkHadoopUtil.scala:68)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.security.auth.Subject.doAs(Subject.java:415)
        at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1628)

在本地独立模式下,可以使用“spark.executor.extraClassPath=path/to/jar”解决此问题,但在具有多个节点的集群上则无济于事。

我已经尝试了所有已知的(对我而言)方法,例如使用 --jars、执行程序(甚至驱动程序)额外的类和库路径、sc.addJar 也...这没有帮助。

我发现 Spark 在 org.apache.spark.util.Utils$.classForName(Utils.scala:173) 中使用 specific 类加载器来加载序列化程序类,但我真的不明白如何使自定义序列化程序可加载。

应用流程提交比较复杂 - Oozie -> SparkSubmit -> YARN 客户端 -> Spark 应用

问题是 - 有人知道如何使用自定义 spark 序列化程序以及如何解决 ClassNotFound 问题吗?

提前致谢!

【问题讨论】:

  • 发送问题到 spark 用户邮件列表 apache-spark-user-list.1001560.n3.nabble.com/…
  • 如果你手动将罐子放在工人身上,它是否有效?我不确定这个问题是否特定于自定义序列化程序,对我来说似乎更广泛。
  • Yuval,你是对的,似乎是 ClassLoaders/classpath 的问题。花了一些时间后,我发现了以下内容:
  • 你能把你用的spark-submit命令放上去吗?
  • Oozie Spark 动作配置:--master yarn-client --name Example-App --class com.example.Job --driver -memory 1g --executor-memory 1g --num-executors 4 --executor-cores 2 --jars hdfs://some_host:9000/user/${wf:user()}/project/lib/project-core -0.0.1-SNAPSHOT.jar --conf spark.executor.extraClassPath=/home/some_user/project/project-core-0.0.1-SNAPSHOT.jar --verbose hdfs://some_host :9000/user/some_user/project/lib/project-core-0.0.1-SNAPSHOT.jar

标签: hadoop apache-spark hadoop-yarn spark-streaming oozie


【解决方案1】:

之所以会这样,是因为我使用了前缀为 /home/some_user 的 spark.executor.extraClassPath。似乎 Spark 无法从该路径加载任何类,因为 Spark 进程所有者是另一个用户,一旦我将 JAR 放入像 /usr/lib/ 这样的路径,一切正常。

所以,我对用户和 Hadoop/Oozie/Spark 进程所有者感到困惑,但我没想到 ClassLoaders 会出现这种行为 =)

感谢您的帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-29
    • 1970-01-01
    • 2015-05-08
    • 2010-11-01
    • 1970-01-01
    • 2019-05-07
    相关资源
    最近更新 更多