1. 现象描述
在进行yarn探测开发的时候,我们的设计是提交一个wordcount的MapReduce作业,根据作业运行的结果作为yarn集群可用性的指标。一般的wordcount的作业,在运行阶段时候使用hdfs进行读写操作。为了摆脱这个限制,我们自己实现了一个wordcount作业。使用这个WordCount.class作为jar提交作业会报SimpleOutputFormat.class not found错误。
上图是wordcount实现方式。
为了解决这个问题,在进行yarn探测开发时,我们的做法是把WordCount.class单独打包放到resources/lib下作为第三方jar使用,通过setJar(path)的方式来提交这个wordcount作业。由此就需要把resources/lib下的wordcount.jar拷贝到本地某个目录下,并且获得这个目录路径。
上图为具体实现方式。
实现了这个逻辑后,我们测试还是会报SimpleOutputFormat.class not found错误。
2. 排查原因
我们对最初版的代码进行对比测试怀疑是在本地生成的wordcount.jar有问题,我们对打出的原始wordcount.jar和在服务器生成的wordcount.jar进行了MD5比较,发现两者不一致。
我们把经过maven打包生成的mozi-detector.jar进行解压,对比了BOOT-INF/classes/lib/wordcount.jar和原始的wordcount.jar的MD5,发现不一致。而且执行java -jar wordcount.jar会报Invalid or corrupt jarfile的错误,由此可推断maven在打包的过程中对wordcount.jar进行了某种处理,导致了文件损坏。
经过对比排查,定位到在pom.xml里配置了一个build标签,删除这个build配置后恢复正常。查阅资料,使用这个配置之后,maven在打包之后会对在resources目录下的文件使用UTF-8转码保存,会导致resource目录下的二进制文件损坏。
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.yml</include>
<include>**/*.properties</include>
<include>**/*.jar</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
3. 解决方式
在<includes>下加一个<excludes>排除文件,或者不添加<include>.