Отправка Spark не работает с зависимостью Protobuf

#apache-spark #kubernetes #apache-spark-sql #sbt #protocol-buffers

#apache-spark #kubernetes #apache-spark-sql #sbt #протокол-буферы

Вопрос:

Apache Spark: 3.0.0 Protobuf: 3.5.1

Исключение: "main" java.lang.NoSuchMethodError: com.google.protobuf.Descriptors$Descriptor.getOneofs()Ljava/util/List;

Проблема: при отправке моего приложения spake scala в моем локальном kubernetes я получаю: "java.lang.NoSuchMethodError: com.google.protobuf.Descriptors$Descriptor.getOneofs()Ljava/util/List;"

Кажется, существует конфликт в зависимости для Protobuff.

Попробовали несколько вещей, таких какhttps://github.com/nats-io/stan.java/issues/20 но ничего не работает.

моя сборка.sbt:

 name := "test"

version := "0.1"
scalaVersion := "2.12.8"

val sparkVersion = "3.0.0"
val protobufVersion = "3.5.1"

resolvers  = "confluent" at "http://packages.confluent.io/maven/"
resolvers  = Resolver.jcenterRepo
resolvers  = "Spark Packages Repo" at "http://dl.bintray.com/spark-packages/maven"

assemblyMergeStrategy in assembly := {
  case "META-INF/services/org.apache.spark.sql.sources.DataSourceRegister" => MergeStrategy.concat
  case PathList("META-INF", xs@_*) => MergeStrategy.discard
  case "application.conf" => MergeStrategy.concat
  case x => MergeStrategy.first
}

assemblyShadeRules in assembly := Seq(
  ShadeRule.rename("com.google.protobuf.*" -> "shadedproto.@1").inProject
    .inLibrary("com.google.protobuf" % "protobuf-java" % protobufVersion)
)

coverageEnabled.in(ThisBuild, IntegrationTest, test) := true

//skipping test cases during package
test in assembly := {}

lazy val server = (project in file("."))
  .configs(IntegrationTest)
  .settings(Defaults.itSettings)

libraryDependencies   = Seq(
  "org.apache.spark" %% "spark-sql" % sparkVersion % Provided,
  "org.apache.spark" %% "spark-sql-kafka-0-10" % sparkVersion,
  "org.apache.kafka" % "kafka-clients" % "2.2.1",
  "org.postgresql" % "postgresql" % postgreSqlVersion,
  "com.google.protobuf" % "protobuf-java" % protobufVersion,
  "com.typesafe" % "config" % "1.4.0"
)



  

Ответ №1:

Чтобы решить эту проблему, вам нужно выполнить две вещи. 1) удалите дублированную библиотеку protobuf, чтобы была доступна только одна ее версия. 2) исправьте любой код, который не использовал версию protobuff, используемую spark.

Один из моих любимых быстрых и грязных приемов для решения этой проблемы — выполнить поиск класса в Intellij конфликтующего класса, в данном случае «Дескрипторов». При этом будут показаны все банки, содержащие класс. Как только вы выясните, какие банки содержат конфликтующий класс, вы можете удалить один из них. Скорее всего, будет проще всего просто сопоставить версию protobuf от spark.

введите описание изображения здесь

Если вы просматриваете зависимости в maven, кажется, что он должен использовать версию v2.5.0, поэтому может возникнуть какая-то другая зависимость.

Возможно, вам потребуется проверить свой код на соответствие этой версии. Какова полная трассировка стека вашей ошибки? Это ваш код, вызывающий функцию protobuf, или это другая библиотека? Если это другая библиотека, вам может потребоваться разветвить библиотеку, чтобы сделать ее совместимой с зависимостями sparks.

Ответ №2:

Поскольку это то, что я в настоящее время пытаюсь решить самостоятельно.

По сути, spark_parent использует protobuf версии 2.5. Вы используете protobufVersion 3.5 введите описание изображения здесь При работе с Intelij не возникнет никаких проблем со следующим кодом, но при попытке spark-отправки кода из файла jar вы столкнетесь со следующей проблемой

введите описание изображения здесь

По сути, spark-parent использует более старую версию protobuf.

За исключением maven, родительская зависимость невыполнима. Перекомпиляция ваших файлов proto до версии 2.5 не обсуждается и не будет работать. Я пробовал затенять jar, но мне не удалось заставить это работать. Просто загрузите код spark, чтобы посмотреть, можно ли что-то сделать из этой части. Вернется назад, когда у меня будет решение для этого

— Решено: вам не нужно создавать Fat Jar, чтобы заставить это работать. Вы можете использовать экспериментальную функцию, чтобы заставить spark использовать ваш пакет. Теперь я также использую Spring Boot, поэтому мне не нужно определять свой пакет для выполнения, но это spark-submit, который необходим

 spark-submit  -v --conf spark.driver.userClassPathFirst=true  
--conf spark.executor.userClassPathFirst=true 
--driver-java-options "-Dspring.profiles.active=local -Djava.util.logging.config.file=log4j.properies " 
--jars /path/to/com/google/protobuf/protobuf-java/3.17.3/protobuf-java-3.17.3.jar 
target/SparkStream-0.1.jar
  

Надеюсь, это поможет вам. Также опубликуйте свое решение.

Ответ №3:

Используйте плагин shade, чтобы затемнить вашу версию protobuf. Это должно решить проблему.