2018的最后一个工作日,是在调式和诊断问题的过程中度过,原本可以按时下班,毕竟最后一天了,然鹅,确是一直苦苦挣扎。
废话不多说,先描述一下问题:有一套大数据环境,是CDH版本的,总共4台机子,我们的应用程序与大数据集群之前已经集成完毕,调试没有问题,可以运行Spark任务。而与这个集群集成是17年下半年的事了,这次升级后,发现无法正确的执行任务,不管是程序提交的还是用示例程序SparkPi,或者手动用spark-submit提交,都是执行失败,且Yarn框架调度执行两次。主要错误提示如下:
Diagnostics: java.lang.NoSuchMethodError: org.apache.commons.io.FileUtils.isSymlink(Ljava/io/File;)Z
截图如下:

sprak-submit提交客户端日志截图

yarn:8088任务监控页面任务(与上图不是一个任务,但错误信息一致)
其实,从任务日志错误提示,可以看出,肯定是加载了低版本的包,用了高版本的方法,NoSuchMethod异常再也熟悉不过了,这一点确信后,就需要找这个包在哪里?FileUtils类属于commons-io包,目前有1.4和2.4版本的,其中,1,4中的FileUtils类确实没有isSymlink方法。好了,基本可以确认,程序在使用了这个commons-io-1.4.jar包。
虽然问题确认,但是还是让人很头疼,因为我可以确认,我们自己的应用程序中,只用了2.4的包。为了排序一些常规影响,我们分别使用cdh自带的sparka提交、使用最简单的SparkPi来运行,但都运行失败,并且我还写了一个搜索类所在的包的工具,来运行排查问题。
package com.meritdata.search.tool; import java.io.PrintStream; import java.security.CodeSource; import java.security.ProtectionDomain; public class Utils { public static void search(String name) { try { Class clazz = Class.forName(name); ProtectionDomain pd = clazz.getProtectionDomain(); CodeSource cs = pd.getCodeSource(); System.out.println(name + " location: " + cs.getLocation()); } catch (Throwable e) { e.printStackTrace(); } } }
package com.meritdata.search.tool; public class Search { public static void main(String[] args) { String name = args[0]; Utils.search(name); } }
这是最先开始使用的代码,想验证当前任务加载的包是不是有其他的版本,使用提交命令:
%SPARK_HOME%>.\bin\spark-submit.cmd --master --deploy cluster --files hive-site.xml --class com.meritdata.search.tool.Search search.tool-0.0.1-SNAPSHOT.jar org.apache.commons.io.FileUtils
这个任务运行的结果,打印的是commons-io-2.4.jar。确认后再想,是不是其他地方引用,而这个demo比较简单,没有使用到,因为加载顺序不一样,可能会影响。所以,又完善了一下程序:
package com.meritdata.search.tool; import java.util.Collections; import org.apache.spark.sql.Dataset; import org.apache.spark.sql.Encoders; import org.apache.spark.sql.SparkSession;

