天天看點

spark-submit以叢集方式送出應用報錯:Exception in thread "main" java.sql.SQLException: No suitable driver

一、問題背景

因現場項目臨近上線,在現場測試環境部署背景程式時候出現各種奇怪的問題,這些都是在公司内部測試環境都沒有遇到過的,很有記錄下來的必要。

Spark應用程式的主要業務邏輯是将MySQL中表資料全量同步到Spark中,以yarn-client模式送出執行報錯:

Exception in thread "main" java.sql.SQLException: No suitable driver

看到這個報錯的第一反應就是環境問題,ClassPath路徑下沒有mysql驅動包。

二、錯誤方案

由于筆者當時認為原因就是ClassPath路徑下沒有mysql驅動包,進行了以下操作步驟:

1. 檢視系統的classpath路徑下是否有驅動包

# 檢視使用者環境變量
cat ~/.bash_profile
# 找到export classpath的路徑
# 逐個cd進去,發現沒有mysql驅動包
           

2. 複制mysql-connector-java-5.1.39-bin.jar包到classpath所在的路徑下

重新spark-submit送出應用還是報同樣的錯誤。

3. 檢視應用啟動日志

INFO ZooKeeper: Client environment:java.class.path= ......

裡面看到了Spark安裝目錄下的lib檔案夾下的相關jar包,想到把mysql-connector-java-5.1.39-bin.jar包複制到這個目錄下,但是還是報同樣的錯誤。

4. 想到Spark運作應用是分布式的

是以,就想到把驅動包放到Spark叢集的所有節點上。考慮到工作量的問題,想起可以在指令行中增加--jars的參數。

5. 執行指令增加--jars

--jars ./mysql-connector-java-5.1.39-bin.jar
           

很不幸還是報錯。

三、成功方案之spark-submit指令增加參數

通過第二部分的錯誤嘗試和搜尋網上同樣問題的解決方案,發現隻增加--jars參數确實不可行。于是嘗試再增加--driver-class-path參數。

--jars ./mysql-connector-java-5.1.39-bin.jar \
--driver-class-path ./mysql-connector-java-5.1.39-bin.jar \
           

執行并沒有報錯,成功!

四、成功方案之代碼修改

經過一番折騰,筆者腦海中突然閃過之前好像也遇到Spark從MySQL中讀取資料時報找不到XXX類的情況,于是翻出之前整理的筆記,下面這句話讓我突然意識到了可能是代碼的問題。

//注意:叢集上運作時,一定要添加下句話,否則會報找不到mysql驅動的錯誤
    prop.put("driver","com.mysql.jdbc.Driver")
           

檢視讀取MySQL的工具類代碼,發現确實少了“driver”參數,正确的讀取MySQL資料的代碼如下:

def readMySqlTable(hiveContext:HiveContext, dbTable:String):DataFrame = {
    val jdbcDF = hiveContext.read.format( "jdbc" ).options(
      Map( "url" -> this.url,
           "driver" -> "com.mysql.jdbc.Driver",
           "user" -> this.user,
           "password" -> this.pwd,
           "dbtable" -> dbTable )).load()

    jdbcDF
  }
           

重新打包測試,執行指令中不加--jars和--driver-class-path參數,運作沒有報錯,成功!

五、總結

遇到找不到XXXX類、XXXX方法的報錯,先排查是不是依賴沖突的問題,大部分情況都是因為依賴沖突,版本不相容導緻找不到類或方法的情況。

本文算是一種特殊情況,用壓縮工具打開程式jar包,pom檔案中加入的mysql-connect-java驅動确實打入的jar包中,而且工具類中也加入了Class.forName(“com.mysql.jdbc.Driver”)指令,是以發現問題還是比較困難,記錄下以後就會避免類似的問題。

繼續閱讀