KafkaSpout 为 log4j 抛出 NoClassDefFoundError

Posted

技术标签:

【中文标题】KafkaSpout 为 log4j 抛出 NoClassDefFoundError【英文标题】:KafkaSpout throws NoClassDefFoundError for log4j 【发布时间】:2016-01-08 08:21:47 【问题描述】:

由于某种原因,当我尝试在 Storm 集群上运行拓扑时出现以下错误:

java.lang.NoClassDefFoundError: Could not initialize class org.apache.log4j.Log4jLoggerFactory
  at org.apache.log4j.Logger.getLogger(Logger.java:39)
  at kafka.utils.Logging$class.logger(Logging.scala:24)
  at kafka.consumer.SimpleConsumer.logger$lzycompute(SimpleConsumer.scala:30)
  at kafka.consumer.SimpleConsumer.logger(SimpleConsumer.scala:30)
  at kafka.utils.Logging$class.info(Logging.scala:67)
  at kafka.consumer.SimpleConsumer.info(SimpleConsumer.scala:30)
  at kafka.consumer.SimpleConsumer.liftedTree1$1(SimpleConsumer.scala:75)
  at kafka.consumer.SimpleConsumer.kafka$consumer$SimpleConsumer$$sendRequest(SimpleConsumer.scala:69)
  at kafka.consumer.SimpleConsumer.getOffsetsBefore(SimpleConsumer.scala:128)
  at kafka.javaapi.consumer.SimpleConsumer.getOffsetsBefore(SimpleConsumer.scala:79)
  at storm.kafka.KafkaUtils.getOffset(KafkaUtils.java:77)
  at storm.kafka.KafkaUtils.getOffset(KafkaUtils.java:67)
  at storm.kafka.PartitionManager.<init>(PartitionManager.java:83)
  at storm.kafka.ZkCoordinator.refresh(ZkCoordinator.java:98)
  at storm.kafka.ZkCoordinator.getMyManagedPartitions(ZkCoordinator.java:69)
  at storm.kafka.KafkaSpout.nextTuple(KafkaSpout.java:135)
  at backtype.storm.daemon.executor$fn__3373$fn__3388$fn__3417.invoke(executor.clj:565)
  at backtype.storm.util$async_loop$fn__464.invoke(util.clj:463) at clojure.lang.AFn.run(AFn.java:24)
  at java.lang.Thread.run(Thread.java:745)cg

问题是什么以及如何解决?

以下是我包含的依赖项:

 <dependencies>
    <dependency>
        <groupId>org.apache.storm</groupId>
        <artifactId>storm-core</artifactId>
        <version>0.9.5</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.kafka</groupId>
        <artifactId>kafka_2.10</artifactId>
        <version>0.8.2-beta</version>
    </dependency>
    <dependency>
        <groupId>org.apache.storm</groupId>
        <artifactId>storm-kafka</artifactId>
        <version>0.9.5</version>
    </dependency>
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-asl</artifactId>
        <version>1.9.11</version>
    </dependency>
    <dependency>
        <groupId>org.java-websocket</groupId>
        <artifactId>Java-WebSocket</artifactId>
        <version>1.3.0</version>
    </dependency>
    <dependency>
        <groupId>org.twitter4j</groupId>
        <artifactId>twitter4j-core</artifactId>
        <version>[3.0,)</version>
    </dependency>
    <dependency>
        <groupId>org.twitter4j</groupId>
        <artifactId>twitter4j-stream</artifactId>
        <version>[3.0,)</version>
    </dependency>
</dependencies>

【问题讨论】:

【参考方案1】:

问题是您应该通过以下方式包含 Kafka:

   <dependency>
        <groupId>org.apache.kafka</groupId>
        <artifactId>kafka_2.10</artifactId>
        <version>0.8.1.1</version>
        <exclusions>
            <exclusion>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
            </exclusion>
            <exclusion>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

原因如下:

请注意,ZooKeeper 和 log4j 依赖项被排除在外,以防止与 Storm 的依赖项发生版本冲突。

【讨论】:

是的,我同意你的看法。 :) 所以你会得到我的支持,因为我的回答对于这个与 Kafka 相关的依赖问题更具体,因此对用户来说应该更值得注意。 谢谢,我会尽快(时效到期)。 最近版本的 kafka 也导入了 org.slf4j/slf4j-log4j12;您可能希望将其添加到您的排除列表中 有了 Kafka 0.9.0.0,我发现我也必须&lt;exclusion&gt;&lt;groupId&gt;org.slf4j&lt;/groupId&gt;&lt;artifactId&gt;slf4j-log4j12&lt;/artifactId&gt;&lt;/exclusion&gt;【参考方案2】:

你使用“正确”的日志框架吗?

来自https://storm.apache.org/2013/12/08/storm090-released.html

记录更改

0.9.0 的另一个重要变化与日志记录有关。 Storm 已在很大程度上切换到 slf4j API(由 logback 记录器实现支持)。一些 Storm 依赖依赖于 log4j API,因此 Storm 目前依赖于 log4j-over-slf4j。

这些更改对使用 log4j API 的现有拓扑和拓扑组件有影响。

一般情况下,如果可能,Storm 拓扑和拓扑组件应使用 slf4j API 进行日志记录。

如果您不使用与 Storm 相同的日志框架,则需要将使用的库与拓扑代码一起包含到您的 jar 文件中。

【讨论】:

感谢您的回答,但我刚刚找到了解决方案。现在我还有一个疑问,也许你想看看 - ***.com/questions/33058988/storm-fields-grouping【参考方案3】:

我和你一样在包含kafka的时候也遇到了同样的问题,所以我根据throw异常用另一种方式包含kafka:

SLF4J: Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar on the classpath, preempting ***Error. SLF4J: See alsohttp://www.slf4j.org/codes.html#log4jDelegationLoop for more details.

您可以通过以下方式包含 kafka:

<dependency>
        <groupId>org.apache.kafka</groupId>
        <artifactId>kafka_2.10</artifactId>
        <version>$kafka.version</version>
        <exclusions>
            <exclusion>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-log4j12</artifactId>
            </exclusion>
            <exclusion>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </exclusion>
    </exclusions>
</dependency>

【讨论】:

以上是关于KafkaSpout 为 log4j 抛出 NoClassDefFoundError的主要内容,如果未能解决你的问题,请参考以下文章

2022年NOC软件创意编程(学而思)决赛小学低年级组scratch

kafka+storm结合存在的一些问题与解决方法

struts2异常处理和log4j日志记录怎么弄?

Tech road one step 7-Noc to 13-Nov

使用 Kafka Spout 的 Kafka Storm 集成

latency analysis for real-time communication on NoC