上周发生了一件十分不幸的事,就是之前依靠这篇博文进行的依赖冲突解决方案失灵了,又开始爆No Such类似的error,这次我可没有心情再一点点的排查了,直接寄出大杀器maven helper。maven helper 是一款idea的插件。
Step1: 下载maven helper 插件。
Step2:插件安装完,打开pom文件。可以看到左下角有一个dependency analyzer。
Step3:查看冲突
Step4:排除冲突的依赖,这一点在maven helper里面特别方便。
点击右边的冲突类,使用鼠标右键点击,会跳出来一个页面,这个时候选择EXCLUDE就可以。
更新分割线;
---------------------------------------------------------------------------------------------------------------------------------
一、Flink任务提交集群问题描述
本文的背景是编程语言使用Scala,Flink程序提交的方式是Per-Job Cluster Mode,Flink程序打包形式是采用胖包打包。
Flink程序Jar包提交的过程中,遇到的问题有:
- NoSuchMethodError
- Could not resolve ResourceManager address akka....
- ClassNotFoundException
- NoClassDefFoundError
上述的所有问题的根源都是maven的pom信息填写不正确,下面具体情况进行具体分析。
二、异常情况分析
2.1 NoSuchMethodError 和NoClassDefFoundError分析
这个异常就是找不到特定方法,这种异常的造成有两个原因。
1、有两个名字和引用位置都相同的类,这就导致了JVM对类进行加载的时候,找不到具体要加载哪个类,有可能同一个Jar包存在多个版本。
2、如果是提交到集群的话,那么极有可能有可能就是程序打包的时候,没有将需要的类打入到Jar包里面。
原因1的解决方案和方法:
使用Idea查看同名引用的类有哪些,找到其对应的Jar包。
在Pom文件中剔除掉冲突的Jar包(仅作为举例说明,按实际需求来就OK)
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.http</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
原因2的解决方案和办法:
原因2就是打胖包的时候,相关依赖没有完全打进去。解决办法是使用maven插件打完整包
<build>
<plugins>
<!-- We use the maven-shade plugin to create a fat jar that contains all necessary dependencies. -->
<!-- Change the value of <mainClass>...</mainClass> if your program entry point changes. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<executions>
<!-- Run shade goal on package phase -->
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<excludes>
<exclude>org.apache.flink:force-shading</exclude>
<exclude>com.google.code.findbugs:jsr305</exclude>
<exclude>org.slf4j:*</exclude>
<exclude>log4j:*</exclude>
</excludes>
</artifactSet>
<filters>
<filter>
<!-- Do not copy the signatures in the META-INF folder. Otherwise, this might cause SecurityExceptions when using the JAR. -->
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.tunan.flink.StreamingJob</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<!-- Java Compiler -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!-- Scala Compiler -->
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.2.2</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
<configuration>
<args>
<arg>-nobootcp</arg>
</args>
</configuration>
</plugin>
<!-- Eclipse Scala Integration -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.8</version>
<configuration>
<downloadSources>true</downloadSources>
<projectnatures>
<projectnature>org.scala-ide.sdt.core.scalanature</projectnature>
<projectnature>org.eclipse.jdt.core.javanature</projectnature>
</projectnatures>
<buildcommands>
<buildcommand>org.scala-ide.sdt.core.scalabuilder</buildcommand>
</buildcommands>
<classpathContainers>
<classpathContainer>org.scala-ide.sdt.launching.SCALA_CONTAINER</classpathContainer>
<classpathContainer>org.eclipse.jdt.launching.JRE_CONTAINER</classpathContainer>
</classpathContainers>
<excludes>
<exclude>org.scala-lang:scala-library</exclude>
<exclude>org.scala-lang:scala-compiler</exclude>
</excludes>
<sourceIncludes>
<sourceInclude>**/*.scala</sourceInclude>
<sourceInclude>**/*.java</sourceInclude>
</sourceIncludes>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<!-- Add src/main/scala to eclipse build path -->
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/scala</source>
</sources>
</configuration>
</execution>
<!-- Add src/test/scala to eclipse build path -->
<execution>
<id>add-test-source</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/test/scala</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
2.2 ClassNotFoundException
这是一个创建错误,错误的原因在于引用该class所属的Jar包
2.3 Could not resolve ResourceManager address akka....
这个不能创建RPC的原因比较多,一般是配置问题或者是Jar运行环境缺失配置文件。
三、为什么引入POM中的plugin解决了打包问题
这个POM当中引入了maven-shade-plugin、maven-compiler-plugin、scala-maven-plugin、build-helper-maven-plugin这四个插件,为啥引入这4个插件就能解决打包问题。
3.1 maven-compiler-plugin
代码自动化编译工具,官网上介绍的功能有源代码编译、测试代码编译、对应的JavaDoc生成
3.2 maven-shade-plugin
代码打包工具,发挥作用的阶段是程序build过程中的打包阶段。
3.3 scala-maven-plugin
Scala代码编译插件
3.4 build-helper-maven-plugin
这个是整个配置文件中最重要的一个插件。上面添加的类都是maven开头的,也就是maven官方提供的,但是上面的这些插件都不知道scala源码的位置。现在需要一个插件来识别鉴定Scala Source源码。
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/scala</source>
</sources>
</configuration>
</execution>
<execution>
<id>add-test-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/test/scala</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
后面两个插件的官方文档补充:https://docs.scala-lang.org/tutorials/scala-with-maven.html