1.前言

目前负责的一个项目用到了一些大数据组件,如:spark,hadoop等,负责大数据项目的是其他小组,他们写完调试好就把源代码直接发给我们,我们在本地调试了也没什么问题,原以为就可以开心的部署上线,没想到一个编译问题卡了4天才解决!

2.解决过程

xx项目是Java 1.8和Scala 2.12.0混合开发的,依赖管理使用的是Maven 3.6.1,编译打包用到了一个插件: scala-maven-plugin。之前我也没有接触过类似的项目,不过都是maven,应该没有多大问题。具体的插件配置如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
 <plugin>
                <groupId>net.alchim31.maven</groupId>
                    <artifactId>scala-maven-plugin</artifactId>
                <version>3.2.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>add-source</goal>
                            <goal>compile</goal>
                            <goal>testCompile</goal>
                        </goals>
                        <configuration>
                            <jvmArgs>
                                <!-- 需要的配置 -->
                                <jvmArg>-Xss700m</jvmArg>
                            </jvmArgs>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

使用以上配置在本地编译打包确实是没用问题了,但是一放到了服务器上就编译失败了。我怀疑是maven的版本有问题,于是替换了好几个maven版本,但是还是报一样的错。

1599188298261

错误非常明显,是未找到Trees这个类,但我查找了下依赖,确实是添加了的。。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-reflect</artifactId>
            <version>2.12.0</version>
        </dependency>
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-library</artifactId>
            <version>2.12.0</version>
        </dependency>

1599188438927

又开始觉得是依赖冲突了? 在使用了IDEA的Maven Helper插件排除完依赖冲突后,还是没能解决问题,这个问题好奇怪,scala.reflect.internal.Trees这个类根本没有使用到。

之后又开始更新Scala的依赖版本和scala-maven-plugin插件的版本,由于项目代码不兼容,这个尝试失败了。我又想起来这台机器装了Scala 2.12.0的环境,会不会是编译的时候使用了这个SDK环境呢?抱着这个想法,我开始在另外一台linux机器上尝试复现这个场景。

1599188827596

pom文件中指定Scala的位置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
   <plugins>
            <plugin>
                <groupId>net.alchim31.maven</groupId>
                    <artifactId>scala-maven-plugin</artifactId>
                <version>3.2.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>add-source</goal>
                            <goal>compile</goal>
                            <goal>testCompile</goal>
                        </goals>
                        <configuration>
                            <jvmArgs>
                                <!-- 需要的配置 -->
                                <jvmArg>-Xss700m</jvmArg>
                            </jvmArgs>
                            <scalaHome>/usr/local/scala-2.12.0</scalaHome>
                            <scalaVersion>2.12.0</scalaVersion>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

做完这些操作后,本台机器的mvn compile命令执行成功了,可是放到真正编译环境的还是报原来的错~ ,其实到这里我都准备放弃了,不如本地打包完毕直接传到服务器,但是甲方要求必须完成自动化操作,所以……

在我对面电脑屏幕上的pom文件毫无进展的时候,我看到了scala-libraryscala-reflect两个依赖,既然我都指定了scala的环境,岂不是就用不到这两个依赖了?因为scala是包含这俩包的。

1599189328766

但是由于在IDEA中没指定SDK,scala-library这个依赖是没法去除了,所以我就把scala-reflect排除了,在服务器上再次执行:mvn clean scala:compile compile, 成功了!

1599189492579

看到BUILD SUCCESS 出现的时候,我真是太激动了!还好没放弃!到这还不算完成,构建完成后还需要把这个包提交到spark集群去运行,运行之后又报错找不到主类MainClass, 不过这个问题在我看来是比较简单的,加个参数就OK了

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.4.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <filters>
                                <filter>
                                    <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.AppendingTransformer">
                                    <resource>META-INF/spring.handlers</resource>
                                </transformer>
                                 <transformer
                                         implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                     <mainClass>main.JKMeans</mainClass>
                                 </transformer>
                                <transformer
                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                    <resource>META-INF/spring.schemas</resource>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

再次打包,成功提交到了集群运行!

3.总结

这个问题可真是花费了我不少时间,在我花了三天时间不停的更换版本,重复实验后,我真的要放弃解决了。在那晚我跑步的时候,脑中突然出现了解决的思路,心想着赶紧回去试试,其实当时我就想到我肯定能解决这个问题,后来也就真的解决了,可见真的不能半途而废啊,说不定某个时刻就有了思路呢?在日常开发的时候,我遇到问题基本上是先搜索一番,看看有没有近似的问题,搜索不到在自己动手尝试看看能不能解决,如果不行的话就赶紧问问大佬,如果还是不行的话就自己另想思路换个角度解决这个问题,比如看看能不能改变下需求,当然这个也是不太友好的。其实有时候遇到些强制性,无法变通的问题,真是挺头疼,不过好在自己最后都能解决。虽然处理的时间长,花费的精力多,也算是经验积累吧,至少以后处理起来不会那么麻烦了。