记一个 protobuf 的 jar 包冲突
尝试使用 spark 以 bulkload 的方式写 HBase 时,遇到一个问题,错误堆栈如下
19/02/02 09:00:43 ERROR Utils: Aborting task java.lang.NoSuchMethodError: org.apache.hadoop.hbase.util.ByteStringer.wrap([B)L/com/google/protobuf/ByteString; at org.apache.hadoop.hbase.io.hfile.HFile$FileInfo.write(HFile.java:709) at org.apache.hadoop.hbase.io.hfile.AbstractHFileWriter.writeFileInfo(AbstractHFileWriter.java:184) at org.apache.hadoop.hbase.io.hfile.HFileWriterV2.close(HFileWriterV2.java:346) at org.apache.hadoop.hbase.regionserver.StoreFile$Writer.close(StoreFile.java:996) at org.apache.hadoop.hbase.mapreduce.HFileOutputFormat2$1.close(HFileOutputFormat2.java:269) at org.apache.hadoop.hbase.mapreduce.HFileOutputFormat2$1.close(HFileOutputFormat2.java:277) at org.apache.spark.internal.io.HadoopMapReduceWriteConfigUtil.closeWriter(SparkHadoopWriter.scala:357) at org.apache.spark.internal.io.SparkHadoopWriter$$anonfun$4.apply(SparkHadoopWriter.scala:133) at org.apache.spark.internal.io.SparkHadoopWriter$$anonfun$4.apply(SparkHadoopWriter.scala:123) at org.apache.spark.util.Utils$.tryWithSafeFinallyAndFailureCallbacks(Utils.scala:1414) at org.apache.spark.internal.io.SparkHadoopWriter$.org$apache$spark$internal$io$SparkHadoopWriter$$executeTask(SparkHadoopWriter.scala:135) at org.apache.spark.internal.io.SparkHadoopWriter$$anonfun$3.apply(SparkHadoopWriter.scala:79) at org.apache.spark.internal.io.SparkHadoopWriter$$anonfun$3.apply(SparkHadoopWriter.scala:78) at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:87) at org.apache.spark.scheduler.Task.run(Task.scala:109) at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:345) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)
一开始以为是找不到 com.google.protobuf.ByteString,怎么都没想明白。后来找同事讨论,确定问题是找不到 return 为 com.google.protobuf.ByteString 的 org.apache.hadoop.hbase.util.ByteStringer.wrap 的函数
原因如下:
同时引用了 org.apache.hbase:hbase-shaded-client 和 org.apache.hbase:hbase-protocol,其中都有类 org.apache.hadoop.hbase.util.ByteStringer 和 方法 wrap,但是返回值分别为 org.apache.hadoop.hbase.shaded.com.google.protobuf.ByteString 和 com.google.protobuf.ByteString。前者被打进 jar 包,于是有了之前的错误。
更进一步,发生这个错误的原因,是在引用 hbase 依赖的时候,同时引用了 shaded 和非 shaded,这是错误的。于是改成都使用 shaded 的 hbase 依赖。