問題
在初用spark streaming 1.5.2 自帶的low level 連接kafka例子(JavaDirectKafkaWordCount)時短蜕,出現(xiàn)如下錯誤:
java.lang.NoSuchMethodError: net.jpountz.util.Utils.checkRange([BII)V
at org.apache.kafka.common.message.KafkaLZ4BlockInputStream.read(KafkaLZ4BlockInputStream.java:176)
根據(jù)網(wǎng)上的解答蜗元,這是因?yàn)閗afka用了1.2版本lz4,? 但是程序運(yùn)行時使用了1.3版的lz4捏萍。 由于兩個版本中的checkRange方法差異大,1.3版的Utils類沒有checkRange方法了淹仑,所以報(bào)NoSuchMethodError丙挽。參見這里。
修改lz4版本
查看項(xiàng)目依賴了哪個版本的lz4: mvn dependency:tree
發(fā)現(xiàn)程序用了spark-core中的net.jpountz.lz4, 是1.3版的匀借,而不是kafka對應(yīng)的1.2版颜阐,所以出錯。
于是我將net.jpountz.lz4 從spark-core中去除:
重新查看lz4的依賴關(guān)系:mvn dependency:tree
上圖可以看出已經(jīng)使用了1.2版的lz4吓肋。
問題依舊
修改版本號后重新在yarn中運(yùn)行凳怨,發(fā)現(xiàn)還是報(bào)“java.lang.NoSuchMethodError: net.jpountz.util.Utils.checkRange([BII)V” 這個錯。
這說明程序還是用的1.3版lz4, 這是什么原因呢?
問題解決 spark.yarn.user.classpath.first=true
我從這篇博客得到啟發(fā)肤舞,很可能1.2版的lz4被yarn自帶hadoop jar包中的1.3版lz4覆蓋了紫新。于是我參照那篇博客,在spark-submit 命令中設(shè)置spark.yarn.user.classpath.first=true :
--conf spark.yarn.user.classpath.first=true \
--jars /your path/spark-streaming-kafka_2.10-1.5.2.jar \
這樣設(shè)置后yarn中優(yōu)先使用用戶傳上去的jar包李剖,保證了lz1.2不被覆蓋弊琴。yarn中的environment UI可以看到優(yōu)先使用了spark-streaming-kafka_2.10-1.5.2.jar:
結(jié)論
解決本問題的需要兩步:
1.在pom.xml中盡量去除1.3版的lz4, 可以使用maven的<exclusion>去除杖爽。
2.在yarn上運(yùn)行是設(shè)置“spark.yarn.user.classpath.first=true”參數(shù),保證1.2版的lz4優(yōu)先被使用, 不被hadoop相關(guān)jar包中的lz4覆蓋紫皇。