springboot工程提交distcp报错CopyOutputFormat not found解决办法

问题描述

在用springboot工程提交distcp.execute()任务时,YARN报错如下:

org.apache.hadoop.yarn.exceptions.YarnRuntimeException: java.lang.RuntimeException: java.lang.ClassNotFoundException: Class com.xxx.hadoop.tools.mapred.CopyOutputFormat not found
	at org.apache.hadoop.mapreduce.v2.app.MRAppMaster$2.call(MRAppMaster.java:518)
	at org.apache.hadoop.mapreduce.v2.app.MRAppMaster$2.call(MRAppMaster.java:498)
	at org.apache.hadoop.mapreduce.v2.app.MRAppMaster.callWithJobClassLoader(MRAppMaster.java:1593)
	at org.apache.hadoop.mapreduce.v2.app.MRAppMaster.createOutputCommitter(MRAppMaster.java:498)
	at org.apache.hadoop.mapreduce.v2.app.MRAppMaster.serviceInit(MRAppMaster.java:284)
	at org.apache.hadoop.service.AbstractService.init(AbstractService.java:163)
	at org.apache.hadoop.mapreduce.v2.app.MRAppMaster$5.run(MRAppMaster.java:1551)
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.security.auth.Subject.doAs(Subject.java:422)
	at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1911)
	at org.apache.hadoop.mapreduce.v2.app.MRAppMaster.initAndStartAppMaster(MRAppMaster.java:1548)
	at org.apache.hadoop.mapreduce.v2.app.MRAppMaster.main(MRAppMaster.java:1481)
Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: Class com.xxx.hadoop.tools.mapred.CopyOutputFormat not found
	at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:2195)
	at org.apache.hadoop.mapreduce.task.JobContextImpl.getOutputFormatClass(JobContextImpl.java:223)

再次确保依赖包存在,并切换springboot版本(2.2.X换成1.5.19)后,还是无济于事。

解决方案

问题排查

通过将distcp中的job.setOutputFormatClass(CopyOutputFormat.class);代码注释带掉,程序卡住;然后在YARN UI页面看到NM机器,去NM机器上找正在执行的job的jar包,发现jar被被重命名为job.jar,里面的内容为springboot全部内容(包含springboot目录结构,这是不合理的)。

springboot打成jar包为可执行jar包,改变了打包后的目录结构,其目录包含BOOT-INF/class等文件夹,这两层目录对于YARN来说是多余的。造成找不到class。

解决方案
1. 想办法改变springbootjar包的结构

网络上大多数的去掉springboot BOOT-INF文件夹方法不可行。更改后,jar包不可执行。如下pom是不行的。

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <skip>true</skip>
    </configuration>
</plugin>

是否有办法更改springboot包结构,并可执行呢?暂未找到。

2. 将distcp依赖包打进jar包

通过jar uf xxx.jar file将distcp包打进jar的根目录,测试,暂未生效。

3. 解决:打成war包

将springboot打成war,放置外置tomcat,问题解决。
springboot版本:1.5.19
<version>1.5.19.RELEASE</version>
jar包换war包设置:
pom.xml

		//1
		<packaging>war</packaging>
		//2
		<dependency>
       		 <groupId>org.springframework.boot</groupId>
        	 <artifactId>spring-boot-starter-web</artifactId>
        <!--移除默认启动容器-->
            <exclusions>
                <exclusion>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- 使用外部容器-->
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-servlet-api</artifactId>
            <version>7.0.47</version>
            <scope>provided</scope>
        </dependency>
...

增加启动类(在原启动类同级目录)

package com.xxx.antyportal;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;

public class SpringBootStartApplication extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        // 注意这里要指向原先用main方法执行的Application启动类
        return builder.sources(xxxPortalApplication.class);
    }
}

vim job.jar
打成war后,放置tomcat,在任务运行时,及时查看job.jar结构:

META-INF/
META-INF/MANIFEST.MF
com/
com/xxx/
com/xxx/hadoop/
com/xxx/hadoop/tools/
com/xxx/hadoop/tools/mapred/
com/xxx/hadoop/tools/mapred/lib/
com/xxx/hadoop/tools/util/
com/xxx/hadoop/tools/CopyListing$AclsNotSupportedException.class
com/xxx/hadoop/tools/CopyListing$DuplicateFileException.class
com/xxx/hadoop/tools/CopyListing$InvalidInputException.class
com/xxx/hadoop/tools/CopyListing$XAttrsNotSupportedException.class
com/xxx/hadoop/tools/CopyListing.class
...
com/xxx/hadoop/tools/util/ThrottledInputStream.class
distcp-default.xml

可以看到,正确的job.jar结构如上。并不是整个springboot 包,而是job需要的class文件(已经到Class级别了),并且根目录就是从com开始,不含包裹。

小结

springboot整合distcp出现找不到类的情况(或许其他MR任务也有类似问题),通过将jar包放置外部tomcat解决。后期尝试使用jar仍可访问的方案。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值