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 会有这样的行为 =)
感谢您的帮助!
我正在尝试使用 自定义 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 会有这样的行为 =)
感谢您的帮助!