Spark 自定义序列化程序导致 ClassNotFound

Spark custom serializer leads to ClassNotFound

我正在尝试使用 自定义 spark 序列化程序,定义为:

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

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

16/04/01 18:41:11 信息 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.run(URLClassLoader.java:366)
        at java.net.URLClassLoader.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(SparkEnv.scala:266)
        at org.apache.spark.SparkEnv$.instantiateClassFromConf(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.apply$mcV$sp(CoarseGrainedExecutorBackend.scala:183)
        at org.apache.spark.deploy.SparkHadoopUtil$$anon.run(SparkHadoopUtil.scala:69)
        at org.apache.spark.deploy.SparkHadoopUtil$$anon.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、执行器(甚至驱动程序)额外的 class 和库路径,sc.addJar 也...没用。

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

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

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

提前致谢!

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

所以,我混淆了用户和 Hadoop/Oozie/Spark 流程所有者,但我没想到 ClassLoaders 会有这样的行为 =)

感谢您的帮助!