Spark Streaming集成Kafka出现NoSuchMethodError错误,求解决方法
这个问题我之前帮好几个开发者排查过,核心原因基本都是依赖版本冲突搞的鬼,尤其是Kafka客户端和Spark Streaming的Kafka适配组件版本不兼容。结合你的环境配置,我给你一步步拆解解决方案:
Spark Streaming和Kafka的适配组件(spark-streaming-kafka-0-10)是严格绑定版本的:你的Spark是2.2.1,对应的spark-streaming-kafka-0-10版本必须也是2.2.1,而且Scala版本要对应2.11——你选的spark-streaming-kafka-0-10-assembly_2.11-2.2.1包是对的,但问题大概率出在Kafka客户端的版本冲突上。
你遇到的NoSuchMethodError,本质是运行时加载的Kafka客户端版本,和Spark Streaming组件依赖的版本不一致。Spark 2.2.1的spark-streaming-kafka-0-10底层依赖的是Kafka 0.10.2.x版本的客户端,而你用的是Kafka 1.0.0或者0.10.0.0,这两个版本的KafkaConsumer.subscribe方法参数有变化,Spark组件是基于0.10.2.x开发的,加载低版本客户端自然找不到对应方法。
强制统一Kafka客户端版本
在你的项目依赖(比如SBT或Maven)里,明确指定Kafka客户端版本为Spark依赖的对应版本(Spark 2.2.1对应kafka-clients:0.10.2.1),同时排除掉其他来源的kafka-clients依赖,避免冲突。举个SBT的配置例子:libraryDependencies ++= Seq( "org.apache.spark" %% "spark-streaming" % "2.2.1" % Provided, "org.apache.spark" %% "spark-streaming-kafka-0-10" % "2.2.1" % Provided, "org.apache.kafka" % "kafka-clients" % "0.10.2.1" force() )提交任务时避免重复依赖
用--jars指定assembly包时,要确保你的项目打包时没有重复打包kafka-clients,也不要同时引入其他Kafka相关jar包,否则会再次触发版本冲突。排除Spark环境的默认冲突依赖
有些Spark集群可能自带了旧版本的Kafka客户端jar包,你可以通过spark-submit的--exclude-packages参数排除掉默认的kafka-clients,比如:spark-submit --exclude-packages org.apache.kafka:kafka-clients \ --jars spark-streaming-kafka-0-10-assembly_2.11-2.2.1.jar \ your-app.jar用正确方式测试官方示例
官方的Spark Streaming Kafka示例,直接用spark-submit指定正确的assembly包运行即可,别额外加其他Kafka jar包——assembly包已经包含了适配好的依赖:spark-submit --class org.apache.spark.examples.streaming.KafkaWordCount \ --jars spark-streaming-kafka-0-10-assembly_2.11-2.2.1.jar \ $SPARK_HOME/examples/jars/spark-examples_2.11-2.2.1.jar \ localhost:9092 test-topic
你可以用spark-shell验证加载的kafka-clients版本,确认是否是指定的0.10.2.1版本:
scala> Class.forName("org.apache.kafka.clients.consumer.KafkaConsumer").getProtectionDomain().getCodeSource().getLocation()
如果输出的jar包路径不是你指定的版本,说明还有隐藏的依赖冲突,需要继续排查。
内容的提问来源于stack exchange,提问作者Erhan

