<
Spark踩坑记(二)
>
上一篇

Spark源码学习笔记(一)
下一篇

Spark踩坑记(一)
第三方包与spark集群guava包冲突

前不久提交了个任务到集群中,死活不通过,查看日志,发现guava包冲突。项目中用了个第三方包,该第三方包使用了guava包,版本是19.0。而spark集群内部也会使用guava包,集群用的是CDH的,spark版本2.3,但是我最后查到guava版本竟然是11.0.2,如何查看集群jar版本,通过spark history server随意进入一个application下,然后点击上方Environment,在该页面下有Classpath Entries,如下图

guava版本

出现该冲突的原因是JVM加载jar,如果有多个版本的jar,默认会先使用spark集群内部的,JVM一旦加载后,就不会进行第二次加载,如果运用了高版本的jar的一些特性,也就会无法运行程序。


###解决方案

方案一:升级集群内部jar版本,且不说该方式不好评估升级jar后对集群带来的负面影响,该方式有些治标不治本吧,以后如果其他jar更新,集群每次都要更新jar版本,成本也太大了,不推荐使用

方案二:使用shade方式替换包,推荐该方式

1)maven管理

修改pom.xml

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <relocations>
                                <relocation>
                                    <pattern>com.google.common</pattern>
                                    <shadedPattern>com.xxx.shaded.com.google.common</shadedPattern>
                                </relocation>
                            </relocations>
                            <filters>
                                <filter>
                                    <artifact>*:*</artifact>
                                    <excludes>
                                        <exclude>META-INF/maven/**</exclude>
                                    </excludes>
                                </filter>
                            </filters>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

2) sbt管理

修改项目目录的project/plugins.sbt,如果没有该文件则创建该文件,添加assembly插件addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.10")

修改build.sbt

assemblyShadeRules in assembly := Seq(
  ShadeRule.rename("com.google.common" -> "com.xxx.shaded.com.google.common").inAll
)

assembly插件打的是个fat jar,需要注意的是maven方式打得fat jar是没办法完成包名替换的,还是会存在guava包冲突


本人使用的是maven方式,打完包后需要验证是否替换包名成功

下载个jd-gui工具验证,官方下载地址,下载完安装成功后打开,拖动jar包进入应用程序窗口内会自动打开jar包,包名未完成替换jar如下图 未替换图片

替换成功后的截图如下,可见com.google.common.base变成了com.feiniu.shaded.com.google.common包 替换成功图片


总结下,无论是自己项目中直接引入guava包,还是引用的第三方包用了guava包都可以完成替换,类推下,所以其他包与spark集群包冲突都可以通过shade化来解决

Top
Foot