Netty版本与Spark + Elasticsearch Transport冲突

时间:2017-11-30 21:15:06

标签: scala apache-spark elasticsearch sbt netty

这有几个先前的问题,有答案,但答案往往没有足够清晰的信息来解决问题。

我正在使用Apache Spark将数据摄取到Elasticsearch中。我们正在使用X-Pack安全性及其相应的传输客户端。我正在使用传输客户端在特殊情况下创建/删除索引,然后使用Spark进行提取。当我们的代码到达client.close()时,抛出异常:

Exception in thread "elasticsearch[_client_][generic][T#2]" java.lang.NoSuchMethodError: io.netty.bootstrap.Bootstrap.config()Lio/netty/bootstrap/BootstrapConfig;
        at org.elasticsearch.transport.netty4.Netty4Transport.lambda$stopInternal$5(Netty4Transport.java:443)
        at org.apache.lucene.util.IOUtils.close(IOUtils.java:89)
        at org.elasticsearch.common.lease.Releasables.close(Releasables.java:36)
        at org.elasticsearch.common.lease.Releasables.close(Releasables.java:46)
        at org.elasticsearch.common.lease.Releasables.close(Releasables.java:51)
        at org.elasticsearch.transport.netty4.Netty4Transport.stopInternal(Netty4Transport.java:426)
        at org.elasticsearch.transport.TcpTransport.lambda$doStop$5(TcpTransport.java:959)
        at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingRunnable.run(ThreadContext.java:569)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)

起初,我认为X-Pack传输客户端正在使用来自Spark的Netty,因此我将其排除在外。即使在排除它之后,我们也会遇到同样的问题。这是我们的依赖集:

    libraryDependencies ++= Seq(
   "com.crealytics" % "spark-excel_2.11" % "0.9.1" exclude("io.netty", "netty-all"),
  "com.github.alexarchambault" %% "scalacheck-shapeless_1.13" % "1.1.6" % Test,
  "com.holdenkarau" % "spark-testing-base_2.11" % "2.2.0_0.7.4" % Test exclude("org.scalatest", "scalatest_2.11") ,
  "com.opentable.components" % "otj-pg-embedded" % "0.9.0" % Test,
  "org.apache.spark" % "spark-core_2.11" % "2.2.0" % "provided" exclude("org.scalatest", "scalatest_2.11") exclude("io.netty", "netty-all"),
  "org.apache.spark" % "spark-sql_2.11" % "2.2.0" % "provided" exclude("org.scalatest", "scalatest_2.11") exclude("io.netty", "netty-all"),
  "org.apache.spark" % "spark-hive_2.11" % "2.2.0" % "provided" exclude("org.scalatest", "scalatest_2.11") exclude("io.netty", "netty-all"),
  "org.apache.logging.log4j" % "log4j-core" %"2.8.2",
  "org.elasticsearch" % "elasticsearch-spark-20_2.11" % "5.5.0" exclude("org.scalatest", "scalatest_2.11") exclude("io.netty", "netty-all"),
  "org.elasticsearch.client" % "x-pack-transport" % "5.5.0",
  "org.elasticsearch.client" % "transport" % "5.5.0",
  "org.elasticsearch.test" % "framework" % "5.4.3" % Test,
  "org.postgresql" % "postgresql" % "42.1.4",
  "org.scalamock" %% "scalamock-scalatest-support" % "3.5.0" % Test,
  "org.scalatest" % "scalatest_2.11" % "3.0.1" % Test,
  "org.scalacheck" %% "scalacheck" % "1.13.4" % Test,
  "org.scalactic" %% "scalactic" % "3.0.1",
  "org.scalatest" %% "scalatest" % "3.0.1" % Test,
  "mysql" % "mysql-connector-java" % "5.1.44"
      )

我验证了sbt dependencyTree SBT并未排除来自Spark和spark-excel的netty,我不知道为什么......我们正在使用SBT 1.0.4。

更新:spark-submit / Spark是罪魁祸首,请在下面回答!

3 个答案:

答案 0 :(得分:2)

好的,经过多次考验和磨难,我明白了。问题不在于SBT没有排除图书馆,而是完全排除了它们。问题在于,即使我排除了任何不是4.1.11.Final的Netty版本,Spark也在使用自己的罐子,在SBT外部和我建造的jar。

运行spark-submit时,它包含$SPARK_HOME/lib目录中的jar。其中一个是Netty 4的旧版本。这个问题显示了这个问题:

bootstrap.getClass().getProtectionDomain().getCodeSource()

结果是/usr/local/Cellar/apache-spark/2.2.0/libexec/jars/netty-all-4.0.43.Final.jar

的jar位置

因此,Spark包含了自己的Netty依赖。当我在SBT中创建我的罐子时,它有正确的罐子。 Spark有一个名为spark.driver.userClassPathFirst的文档in the Spark config documentation的配置,但是当我将其设置为true时,我最终会遇到与使用更高版本的Netty有关的问题。

我决定使用传输客户端,而是使用可靠的旧HTTP请求。

答案 1 :(得分:1)

我遇到了需要将Netty与Spark结合使用的依赖项的相同问题。我也尝试了spark.driver.userClassPathFirst选项但它没有用。我找到了另一种我认为可以分享的解决方法,以防将来对其他人有所帮助。

由于我们正在创建一个与spark-submit一起使用的程序集jar,我想我可以在程序集jar中隐藏依赖项,以便spark-submit可以在没有冲突的情况下引入它自己的Netty版本。我们正在使用https://github.com/sbt/sbt-assembly插件,所以我需要做的就是将其包含在相关模块中的build.sbt中:

assemblyShadeRules in assembly := Seq(
  ShadeRule.rename("io.netty.**" -> "shadenetty.@1").inAll
)

答案 2 :(得分:0)

从spark-core中排除Netty依赖对我们有用

        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-core_2.10</artifactId>
            <version>${spark.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>io.netty</groupId>
                    <artifactId>netty-all</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>io.netty</groupId>
                    <artifactId>netty</artifactId>
                </exclusion>
            </exclusions>
        </dependency>