Apache Zeppelin 遷移 - Jar 包沖突解決與思考

最近整個公司大數(shù)據(jù)集群遷移(cdh -> ambri hdp),隨之 Zeppelin 也需要遷移满哪,由于各個組件版本有變化亦渗,且 Zeppelin 源碼是有過改動的,遷移起來很麻煩任柜。經(jīng)過一周的折騰,終于把 Zeppelin 從 cdh 環(huán)境遷移至 hdp 環(huán)境寒波。同時乘盼,在解決問題期間升熊,對 Java 類加載俄烁,jar 沖突問題有了更進一步的認識。

1 遷移前后環(huán)境

1.1當前環(huán)境

  • zeppelin: 0.7.2
  • hadoop:cdh 2.6.0
  • spark: 2.0

1.2 遷移環(huán)境

  • hdp: 2.6.0.3-8
  • hadoop: 2.7.3.2.6.0.3-8 ( hortonworkds compiled )
  • spark: 2.1

版本有所變化级野,當然得重新編譯 Zeppelin 页屠,指定下 spark hadoop 大版本,重新編譯:

mvn clean package -Pbuild-distr -Pspark-2.1 -Phadoop-version2.7.3 -Pscala-2.11 -DskipTests -Dcheckstyle.skip=true

經(jīng)過配置參數(shù)修改蓖柔,遷移過去 hive 沒問題辰企,spark 運行報錯,經(jīng)過一周的折騰終于解決况鸣,主要是版本依賴沖突問題牢贸。

2 沖突解決

2.1 hadoop 公共組件沖突解決:

  • 現(xiàn)象:執(zhí)行報相關(guān)的任務(wù)報 ClassNotFoundExecption NoSuchMethodError 等錯誤。
  • 沖突的包:hadoop-common.jar 和 hadoop-auth.jar
  • 目錄:$zeppelin_home/lib
  • 解決方案:從 HDP 相關(guān)的目錄拷貝并替換對應(yīng)的包镐捧,版本升級:2.6.0 -> 2.7.3

2.2 libthrift 與 libfb303 jar 沖突解決:

現(xiàn)象:跑 spark sql 報 NoSuchMethodError 錯誤如下:

1. java.lang.NoSuchMethodError:com.facebook.fb303.FacebookService$Client.sendBaseOneway
2. (Ljava/lang/String;Lorg/apache/thrift/TBas
3. at com.facebook.fb303.FacebookService$Client.send_shutdown(FacebookService.java:436)
4. at com.facebook.fb303.FacebookService$Client.shutdown(FacebookService.java:430)
5. at org.apache.hadoop.hive.metastore.HiveMetaStoreClient.close(HiveMetaStoreClient.java:558)
6. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
7. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
8. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
9. at java.lang.reflect.Method.invoke(Method.java:498)
10. at org.apache.hadoop.hive.metastore.RetryingMetaStoreClient.invoke(RetryingMetaStoreClient.java:178)
11. at com.sun.proxy.$Proxy22.close(Unknown Source)

連 hive metastore 后調(diào)用 close() 方法, FacebookService(from: libfb303.jar) 最終調(diào)用 TClient.sendBaseOnewayto: libthrift.jar
查看 libthrift 源碼, 0.9.3 版本有 sendBaseOneway潜索, 而 0.9.2 版本沒有臭增。
結(jié)論: libfb303.jar 的 facebookservice 調(diào)用了 libthrift 0.9.3 版本的中的方法,而 JVM 加載了 0.9.2 版本竹习, 導(dǎo)致 NoSuchMethodError誊抛。

查看 zeppelin 源碼,zeppelin-spark\*.jar整陌,zeppelin-spark-dependencices\*.jar 都 shaded 了 libthrift 這個 jar 包拗窃。
打包信息如下:

INFO] Building jar: D:\flyao\Idea\zeppelin-0.7.2\spark\target\zeppelin-spark_2.10-0.7.2.jar
[INFO]
[INFO] --- maven-shade-plugin:2.3:shade (default) @ zeppelin-spark_2.10 ---
[INFO] Including org.apache.zeppelin:zeppelin-display_2.11:jar:0.7.2 in the shaded jar.
[INFO] Including org.apache.zeppelin:zeppelin-interpreter:jar:0.7.2 in the shaded jar.
[INFO] Including org.apache.thrift:libthrift:jar:0.9.3 in the shaded jar.

jar 所在目錄:

  • $zeppelin_home/lib/interpreter : zeppelin-spark*.jar
  • $zeppelin_home/interpreter/spark/dep : zeppelin-spark-dependencices*.jar
    x
    解決方案:
    升級 libthrift jar 版本:0.9.2 -> 0.9.3
    1.將 pom 里 libthrift 的版本升至 0.9.3
    2.重新打包: mvn clean package -Pspark-2.1 -Phadoop-2.7 -Pscala-2.11 -DskipTests

這里也有一個取巧的方法,將 jar 包解壓刪除 thrift 并重新打包泌辫。通過 linux 下 jar 命令即可完成随夸。

3 Java Jar 包沖突思考

如果深入理解 Java 類加載機制,jar包沖突相關(guān)原因震放,對定位解決這類問題有很大的幫助 逃魄。
一般來說遇到:ClassNotFoundExpection, NoClassDefFoundErrorNoSuchMethodError ,有可能是包沖突造成的澜搅。

先來解釋下這個三個問題的區(qū)別 [1]:

  • ClassNotFoundExpection:是一個可以恢復(fù)的 expection伍俘;動態(tài)加載 class 的時候(Class.forName("") 或 classloader loadClass時),classpath 找不到對應(yīng)的文件勉躺。
  • NoClassDefFoundError :JVM runtime 拋出的 ERROR:compile time 可以找到的 class癌瘾,在 runtime 間(通過 new 或者方法調(diào)用 )無法加載。當然出現(xiàn)問題的情況也有多種:class 文件確實不在饵溅,被修改妨退,這個類依賴的類出現(xiàn)加載問題,或者靜態(tài)初始化拋出異常等蜕企。
  • NoSuchMethodError :同樣是 JVM runtime ERROR咬荷,編譯期間可以找到的方法,runtime 期間找不到了轻掩。這次典型的包沖突導(dǎo)致 NoSuchMethodError幸乒。

3.0 jar 包沖突 - 本質(zhì)

讀完這個 重新看待Jar包沖突問題及解決方案 [3]收獲良多,總結(jié)部分筆記唇牧,對于沖突罕扎,存在兩個場景:

  • 同一個Jar包出現(xiàn)了多個不同版本:相同的 jar 包(名 group artifict),不同的版本:例如開源 jar 包更新版本丐重。libthrift-0.9.2.jar libthrift-0.9.3.jar
  • 同一個類出現(xiàn)在多個不同 Jar 包中:不同的 jar 包(名group artifict )腔召,同一個類(同樣的類限定詞)出現(xiàn)在不同的包中,例如:commons-lang 和 commons-lang3

這兩個場景的存在扮惦,會導(dǎo)致 JVM 加載到了錯誤的類臀蛛,導(dǎo)致與預(yù)期場景不一致出現(xiàn)上面描述的錯誤等,導(dǎo)致出現(xiàn) ClassNotFoundExpection, NoClassDefFoundErrorNoSuchMethodError 等異常崖蜜。

3.1 jar 包沖突 - maven 仲裁機制

因為 maven 的傳遞依賴機制浊仆,maven 引入依賴類似于圖的遍歷烙肺,從子往父溯源,引入所有相關(guān)依賴氧卧。這樣為開發(fā)節(jié)省了效率桃笙,但同時可能引入不同版本的 jar 包,導(dǎo)致在運行時出現(xiàn)包沖突沙绝。存在多個依賴搏明,maven 具體選擇引入哪個依賴,規(guī)范來源于仲裁機制闪檬,仲裁機制如下:

  1. 首先依據(jù) <dependencyManagement> 中聲明的版本星著,此時下面的兩個原則都無效了
  2. 依據(jù)依賴樹中路徑最短的版本
  3. 路徑相同,則按照“第一聲明優(yōu)先”的原則進行仲裁粗悯,即選擇POM中最先聲明的版本

常見的解決依賴沖突的辦法有兩個:

  1. <dependencyManagement> 是解決沖突的常用手段
  2. <exclusions> 排除相關(guān)沖突依賴

下面這段配置取自 Zeppelin pom虚循,聲明選擇的依賴的 avro 版本,同時排除了部分依賴 如 netty样傍。

 <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.apache.avro</groupId>
        <artifactId>avro</artifactId>
        <version>${avro.version}</version>
      </dependency>
      <dependency>
        <groupId>org.apache.avro</groupId>
        <artifactId>avro-ipc</artifactId>
        <version>${avro.version}</version>
        <exclusions>
          <exclusion>
            <groupId>io.netty</groupId>
            <artifactId>netty</artifactId>
          </exclusion>
        </exclusions>
      </dependency>
</dependencyManagement>

3.2 jar 包沖突 - jar 包加載順序

還有一種沖突是同樣的類横缔,出現(xiàn)在不同的包里面,例如 A 和 B 包都有類 C衫哥,JVM 在加載 C 的時候到底是選擇 A 還是 B茎刚。這個選擇取決于:

  1. Jar 包所處的加載路徑,或者換個說法就是加載該 Jar 包的類加載器在 JVM 類加載器樹結(jié)構(gòu)中所處層級撤逢。例如 bootstrap classloader 還是 app classloader 路徑下膛锭。
  2. 文件系統(tǒng)的文件加載順序。這個因素很容易被忽略蚊荣,對于 linux 文件系統(tǒng)來說初狰, 可能是按照文件的 inode 排序決定。所以測試與生產(chǎn)環(huán)境是否一致很重要互例。

3.3 jar 包沖突 - 定位與解決

如果遇到ClassNotFoundExpection, NoClassDefFoundErrorNoSuchMethodError 奢入,有可能是包沖突造成的。

  1. 定位 jar 包: 根據(jù)日志查詢對應(yīng)的 class 所在 jar 包敲霍;可以直接在 IDEA 雙擊 shift 搜索俊马,并定位到 jar 包丁存,或者自己寫段腳本遍歷 jar 包搜索肩杈。
  2. 查看引入方: 通過 mvn dependency:tree -Dverbose -Dincludes=<groupId>:<artifactId> 查看是哪些地方引入。另外可以通過 IDEA Maven helper 插件來查看依賴沖突解寝。
  3. 解決沖突:可用 <excludes> 排除不需要的 Jar 包版本或者在依賴管理 <dependencyManagement> 中申明版本扩然。

[1] https://stackoverflow.com/questions/1457863/what-causes-and-what-are-the-differences-between-noclassdeffounderror-and-classn/1457879#1457879
[2] classnotfoundexception-vs-noclassdeffounderror
[3] 重新看待Jar包沖突問題及解決方案

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市聋伦,隨后出現(xiàn)的幾起案子夫偶,更是在濱河造成了極大的恐慌界睁,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件兵拢,死亡現(xiàn)場離奇詭異翻斟,居然都是意外死亡,警方通過查閱死者的電腦和手機说铃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門访惜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人腻扇,你說我怎么就攤上這事债热。” “怎么了幼苛?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵窒篱,是天一觀的道長。 經(jīng)常有香客問我舶沿,道長墙杯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任括荡,我火速辦了婚禮霍转,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘一汽。我一直安慰自己避消,他們只是感情好,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布召夹。 她就那樣靜靜地躺著岩喷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪监憎。 梳的紋絲不亂的頭發(fā)上纱意,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機與錄音鲸阔,去河邊找鬼偷霉。 笑死,一個胖子當著我的面吹牛褐筛,可吹牛的內(nèi)容都是我干的类少。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼渔扎,長吁一口氣:“原來是場噩夢啊……” “哼硫狞!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤残吩,失蹤者是張志新(化名)和其女友劉穎财忽,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體泣侮,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡即彪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了活尊。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片祖凫。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖酬凳,靈堂內(nèi)的尸體忽然破棺而出惠况,到底是詐尸還是另有隱情,我是刑警寧澤宁仔,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布稠屠,位于F島的核電站,受9級特大地震影響翎苫,放射性物質(zhì)發(fā)生泄漏权埠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一煎谍、第九天 我趴在偏房一處隱蔽的房頂上張望攘蔽。 院中可真熱鬧,春花似錦呐粘、人聲如沸满俗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽唆垃。三九已至,卻和暖如春痘儡,著一層夾襖步出監(jiān)牢的瞬間辕万,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工沉删, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留渐尿,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓矾瑰,卻偏偏與公主長得像砖茸,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子脯倚,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容