解讀spark添加二方包導致依賴沖突排查問題
問題描述
近期發(fā)現(xiàn)了一個線上問題,本地啟動byzer服務是正常的,但打好的docker鏡像就是拋異常跑不起來,而前幾天構建的鏡像是正常的,初步定位到時新的發(fā)布導致的!
于是經過了一系列痛苦的排查。
錯誤堆棧
看byzer-lang最近的提交記錄都在30天前,顯示不會是它的問題,于是根據日志研究。
7bafdda4df93] __MMMMMM__ Total jobs: 1 current job:1 job script:load modelList.`` as __output__
22/02/09 14:58:32 ERROR Executor: Exception in task 0.0 in stage 2.0 (TID 2)
java.lang.IllegalArgumentException: Illegal pattern component: XXX
at org.apache.commons.lang3.time.FastDatePrinter.parsePattern(FastDatePrinter.java:282)
at org.apache.commons.lang3.time.FastDatePrinter.init(FastDatePrinter.java:149)
at org.apache.commons.lang3.time.FastDatePrinter.<init>(FastDatePrinter.java:142)
at org.apache.commons.lang3.time.FastDateFormat.<init>(FastDateFormat.java:384)
at org.apache.commons.lang3.time.FastDateFormat.<init>(FastDateFormat.java:369)
at org.apache.commons.lang3.time.FastDateFormat$1.createInstance(FastDateFormat.java:91)
at org.apache.commons.lang3.time.FastDateFormat$1.createInstance(FastDateFormat.java:88)
at org.apache.commons.lang3.time.FormatCache.getInstance(FormatCache.java:82)
報錯xxx令人不知所措,一開始懷疑是modelList這個腳本在RestController執(zhí)行的時候,攜帶了這個xxx錯誤參數(shù),但因為是鏡像中不好debug,定位堆棧拋異常的是如下代碼:
val jsonDF = limitOrNot {
df.limit(outputSize)
}.toJSON
val scriptJsonStringResult = fetchType match {
case "collect" => jsonDF.collect().mkString(",")看代碼得知是jsonDF.collect().mkString(",")這行的問題,outputSize數(shù)據有問題,但我并沒有在啟動服務的時候請求任何腳本,于是陷入了死胡同。
google后發(fā)現(xiàn)是一個spark2普遍的問題,找到如下文章:
- https://www.codetd.com/en/article/12490356
- https://stackoverflow.com/questions/46429616/spark-2-2-illegal-pattern-component-xxx-java-lang-illegalargumentexception-ill

描述很清晰,是commons-lang3依賴沖突導致的,需要保證commons-lang3依賴在3.5以上。
于是順著這個方向,排了工程里面相關的依賴,本地啟動正常,docker中啟動報錯。。。
于是懷疑是docker環(huán)境問題導致,拉取了最新的docker構建腳本,發(fā)現(xiàn)大量新增代碼,果然是新增代碼的鍋,新增邏輯比較多,于是直接拉上相關同事一起看。
發(fā)現(xiàn)最近docker的lib文件夾下增加了很多jar,spark提交任務的腳本增加了很多插件類:
COPY lib/ansj_seg-5.1.6.jar \
lib/nlp-lang-1.7.8.jar \
lib/${AZURE_BLOB_NAME} \
lib/mlsql-assert-${MLSQL_SPARK_VERSION}_${SCALA_BINARY_VERSION}-0.1.0-SNAPSHOT.jar \
lib/mlsql-excel-${MLSQL_SPARK_VERSION}_${SCALA_BINARY_VERSION}-0.1.0-SNAPSHOT.jar \
lib/mlsql-ext-ets-${MLSQL_SPARK_VERSION}_${SCALA_BINARY_VERSION}-0.1.0-SNAPSHOT.jar \
lib/mlsql-shell-${MLSQL_SPARK_VERSION}_${SCALA_BINARY_VERSION}-0.1.0-SNAPSHOT.jar \
lib/mlsql-mllib-${MLSQL_SPARK_VERSION}_${SCALA_BINARY_VERSION}-0.1.0-SNAPSHOT.jar \
${MLSQL_HOME}/libs/
spark-submit 任務啟動腳本:
$SPARK_HOME/bin/spark-submit --class streaming.core.StreamingApp \ --driver-memory ${DRIVER_MEMORY} \
...
-streaming.plugin.clzznames "tech.mlsql.plugins.ds.MLSQLExcelApp,tech.mlsql.plugins.assert.app.MLSQLAssert,tech.mlsql.plugins.shell.app.MLSQLShell,tech.mlsql.plugins.ext.ets.app.MLSQLETApp"顯然是二方包導致的依賴沖突,而之前花了大量時間改byzer的依賴,打包,部署,重新構建docker都是無用功!
但jar還是比較多,只能窮舉的在docker環(huán)境中一個一個的刪掉,測試是否有啟動異常,在排查到AZURE這個jar的時候發(fā)現(xiàn)了問題,該jar是我們?yōu)榱酥С諥ZURE添加的,已經經過沖突依賴shade處理的,shade重構建的項目在這個REPO下:
GitHub - byzer-org/byzer-objectstore-dep
于是clone項目,使用maven Dependency Analyzer分析:

并沒有commons-lang3這個依賴,于是懷疑是其他依賴導致的沖突,把azure相關的依賴直接引入到byzer的項目中(為了做依賴沖突分析),于是驚奇的發(fā)現(xiàn)commons-lang3又有了:

是因為打包項目為了滿足不同的hadoop版本打包,設置了profiles,導致分析工具失效了:

修復問題
對azure-store項目中的依賴做shade處理:
<profile>
<id>shade</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>org.apache.commons</pattern>
<shadedPattern>shadeio.azure.org.apache.commons</shadedPattern>
</relocation>
<relocation>
<pattern>commons-lang</pattern>
<shadedPattern>shadeio.azure.commons-lang</shadedPattern>
</relocation>
</relocations>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>在byzer-lang中添加統(tǒng)一的版本約束:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
</dependency>
</dependencies>
</dependencyManagement>在啟動byzer的子pom中顯式聲明依賴:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>問題得到解決,另外發(fā)現(xiàn)一個問題,雖然dependencyManagement定義版本這種定義方式有如下規(guī)范:
- 如果子pom中顯式設置了version則以子pom的version為主
- 需要使用父pom依賴時需要聲明依賴并且不設置version
但我測試發(fā)現(xiàn)在azure這個依賴中攜帶的commons-lang3即使不在子pom聲明使用dependencyManagement定義后,其版本也會被約束成3.10而不是以前的3.3。
筆者建議聲明一下避免打包解析樹的時候出現(xiàn)問題。
?總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
IntelliJ IDEA中ajax開發(fā)實現(xiàn)分頁查詢示例
這篇文章主要介紹了IntelliJ IDEA中ajax開發(fā)實現(xiàn)分頁查詢,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-03-03
Java異常處理Guava?Throwables類使用實例解析
這篇文章主要為大家介紹了Java異常處理神器Guava?Throwables類使用深入詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-12-12
mybatis spring配置SqlSessionTemplate的使用方式
這篇文章主要介紹了mybatis spring配置SqlSessionTemplate的使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08
關于SpringBoot使用Redis空指針的問題(不能成功注入的問題)
這篇文章主要介紹了關于SpringBoot使用Redis空指針的問題(不能成功注入的問題),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-11-11

