Spark jar not loaded. Offending class: javax/servlet/Servlet.class,javax.servlet


相关软件版本

Spark1.4.1 ,Hadoop2.6,Scala2.10.5,intelliJ IDEA2014,JDK1.8,Tomcat7

机器及服务:

windows7 :包含JDK1.8,IntelliJ IDEA2014,Tomcat7(在IDEA中直接配置Tomcat, 然后启动工程 );
centos6.6虚拟机:Hadoop伪分布式集群,JDK1.8(Spark直接调用hadoop集群,使用Spark on YARN的方式);

本篇接上篇Java Web提交任务到Spark ;

问题描述:

部署Tomcat,运行java web程序调用Spark,执行Scala开发的Spark程序。并且提交任务到Yarn集群,使用yarn-client(或yarn-cluster)的模式,即Spark on YARN的模式。
部署过程以及遇到问题及解决方法:
1. 直接使用简单的servlet程序运行,同时把scala开发的算法jar包以及spark-assembly-1.4.1-hadoop2.6.0.jar包拷贝到WEB-INF/lib目录下面,启动Tomcat。
2. 启动Tomcat时,由于spark-assembly-1.4.1-hadoop2.6.0.jar中含有javax.servlet包和tomcat的servlet-api.jar冲突。日志如下:

validateJarFile(D:\workspase_scala\java-web1.0\out\artifacts\java_web1_0_war_exploded\WEB-INF\lib\spark-assembly-1.4.1-hadoop2.6.0.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class

这里的解决方式是直接删除spark-assembly-1.4.1-hadoop2.6.0.jar中的javax.servlet包,即:
jar包删除前后对比图
3. 然后再次启动tomcat,这次tomcat即可正常启动,但是调用Spark on YARN,仍然会报错,报错信息在Hadoop的日志监控上面,具体如下:

15/09/16 07:14:03 ERROR yarn.ApplicationMaster: User class threw exception: java.lang.NoClassDefFoundError: javax/servlet/FilterRegistration
java.lang.NoClassDefFoundError: javax/servlet/FilterRegistration
at org.spark-project.jetty.servlet.ServletContextHandler.(ServletContextHandler.java:136)
at org.spark-project.jetty.servlet.ServletContextHandler.(ServletContextHandler.java:129)
at org.spark-project.jetty.servlet.ServletContextHandler.(ServletContextHandler.java:98)
at org.apache.spark.ui.JettyUtils.createServletHandler(JettyUtils.scala:108)atorg.apache.spark.ui.JettyUtils.createServletHandler(JettyUtils.scala:99)
at org.apache.spark.ui.WebUI.attachPage(WebUI.scala:78)
at org.apache.spark.ui.WebUIanonfun$attachTab$1.apply(WebUI.scala:62)atorg.apache.spark.ui.WebUIanonfunattachTab1.apply(WebUI.scala:62)
at scala.collection.mutable.ResizableArrayclass.foreach(ResizableArray.scala:59)atscala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:47)atorg.apache.spark.ui.WebUI.attachTab(WebUI.scala:62)atorg.apache.spark.ui.SparkUI.initialize(SparkUI.scala:61)atorg.apache.spark.ui.SparkUI.(SparkUI.scala:74)atorg.apache.spark.ui.SparkUI.create(SparkUI.scala:190)
at org.apache.spark.ui.SparkUI.createLiveUI(SparkUI.scala:141)atorg.apache.spark.SparkContext.(SparkContext.scala:440)atScalaTest.main(Scala_Test.scala:15)
at Scala_Test.main(Scala_Test.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.apache.spark.deploy.yarn.ApplicationMaster$$anon$2.run(ApplicationMaster.scala:483)
Caused by: java.lang.ClassNotFoundException: javax.servlet.FilterRegistration
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
… 23 more

这个错误是因为删除了spark-assembly-1.4.1-hadoop2.6.0.jar包中的javax.servlet包导致的。
一般的想法是在Spark提交时,添加servlet.jar包,即如下:

“–addJars”,”file:/E:/spark-servlet.jar”,//

添加了这个参数后,可以看到servlet包确实和spark-assembly-1.4.1-hadoop2.6.0.jar一样被上传到了同样的位置:
如下:

2015-09-16 15:44:12 INFO Client:59 - Uploading resource file:/D:/workspase_scala/java-web1.0/out/artifacts/java_web1_0_war_exploded/WEB-INF/lib/spark-assembly-1.4.1-hadoop2.6.0.jar -> hdfs://node88:8020/user/Administrator/.sparkStaging/application_1442408848694_0016/spark-assembly-1.4.1-hadoop2.6.0.jar
2015-09-16 15:44:16 INFO Client:59 - Uploading resource file:/D:/workspase_scala/java-web1.0/out/artifacts/java_web1_0_war_exploded/WEB-INF/lib/spark_filter.jar -> hdfs://node88:8020/user/Administrator/.sparkStaging/application_1442408848694_0016/spark_filter.jar
2015-09-16 15:44:16 INFO Client:59 - Uploading resource file:/E:/spark-servlet.jar -> hdfs://node88:8020/user/Administrator/.sparkStaging/application_1442408848694_0016/spark-servlet.jar

但是,在hadoop的任务监控界面仍然看到缺少javax.servlet.FilterRegistration类,说明配置同样不行。
这里需要说明的是在hadoop的lib包中有servlet-api.jar,但是这个jar里面同样的没有上面的那个类。
4. 根据3的错误推测,既然是报包类找不到,那么肯定可以往hadoop基础环境中加入jar包(同时hadoop基础环境里面已经有servlet-api.jar包),那就直接把servlet.jar包拷贝到$HADOOP_HOME/share/common/下面即可。
那这个servlet.jar怎么获得呢?

其实可以在删除spark-assembly-1.4.1-hadoop2.6.0.jar中的javax.servlet包中的文件前,先复制一个spark-assembly-1.4.1-hadoop2.6.0.copy.jar,然后把spark-assembly-1.4.1-hadoop2.6.0.copy.jar中的除了javax.servlet包其他都删掉,最后得到的jar包重命名为servlet.jar包,然后在上传到$HADOOP_HOME/share/common/即可。
经过测试,发现此种方法可以达到预期效果。

分享,成长,快乐

脚踏实地,专注

转载请注明blog地址:http://blog.csdn.net/fansy1990

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关内容