首页 > 解决方案 > Storm bolt 无法从 spout 反序列化对象

问题描述

我正在使用 Storm 1.1.2、JDK 8(Storm 不喜欢 JDK 9 编译代码)、Kafka 0.11 和 Docker Compose 制作一个 Spring 应用程序。

这个想法是有一个容器化的服务,它可以接收 REST 调用来创建风暴拓扑,然后将它们提交到风暴集群。一切都在本地工作,但是将拓扑提交从提交到本地集群移动到StormSubmitter导致问题。我已经解决了大多数问题,但是有一个奇怪的序列化问题。

我有一个从 Kafka 成功读取的喷嘴。它读取 Protobuf 对象的字节数组,并使用自定义反序列化器从中创建消息。我从这个 spout 读取了两个不同的螺栓,一个打印传入消息(螺栓 A),一个根据字段过滤消息并将它们发送到另一个要聚合的螺栓(螺栓 B)。

我注意到两个螺栓之间的唯一区别是螺栓 B 有一个构造函数,而螺栓 A 没有。

由于某种原因,bolt A 可以毫无问题地从 spout 接收消息并打印它们,但是每次消息到达 bolt B 时,它都会引发异常com.esotericsoftware.kryo.KryoException: Class cannot be created (missing no-arg constructor): my.package.MyProtobufMessage。我看到您可以为类注册序列化程序,但是为什么当螺栓 B 不能时螺栓 A 能够处理消息?

也是单独的问题,但是当我添加第三个拓扑时,nimbus 不会为其分配主管。一个拓扑将包含 2 个作品和 9 个执行人员,第二个拓扑将包含 2 个工作人员和 6 个执行人员,然后我将添加第三个拓扑,该拓扑将显示在 UI 和 Nimbus 日志中,但不会显示在主管日志中。在 UI 中,第三个拓扑将有 0 个工作人员、执行人员和 0 个分配的内存

标签: javaapache-kafkaapache-stormapache-storm-topology

解决方案


您可能很“幸运”,因为 spout 和 bolt A 在同一个 worker 中,而 bolt B 在另一个 worker 中。Storm 不会序列化元组,除非它们被转移到另一个工人,这可能是螺栓 A 可以读取消息的原因。

关于第三个拓扑问题,您需要确保您的主管有足够的工作槽用于您的拓扑。每个主管在 Storm 配置 (storm.yaml) 中定义它愿意运行多少个工作 JVM。我猜前两个拓扑占用了所有插槽。

主管的默认配置是

supervisor.slots.ports:
    - 6700
    - 6701
    - 6702
    - 6703

这允许每个主管上有 4 个工作 JVM。由于工作 JVM 不是共享的,如果您正在运行 2 个拓扑,每个拓扑占用 2 个工作人员,那么您已经用完了所有插槽。您可以添加更多插槽或更多主管机器,或者减少拓扑所需的工作人员数量。


推荐阅读