1

我是 apachestorm 的新手,我编写了包含 1 个 spout 和 2 个 bolt 的代码,当我在一个 worker 上运行这 3 个部分时,代码会正确生成输出,但是当我在 1 个 worker 执行的三个 worker 中运行代码时spout,另一个运行螺栓 1 和最后一个运行螺栓 2,将不会生成输出。具体情况:当我将螺栓1和2放在一个工人中时,产生了输出!

不得不说,发射成功了,发射变量没有问题。

详细说明:我在螺栓 1 的哈希图结构中创建了树,我想在螺栓 2 中挖掘这棵树。在螺栓 1 中插入树中的对象的 id 就像“MyTreeNode@e70014d5”,当我收到这个元组时(哈希图) 在螺栓 2 中,id 更改为类似“MyTreeNode@z5542r12”的内容。

主要问题是什么?

问题是因为更改了对象ID吗?如果是,请告诉我如何解决?

4

1 回答 1

1

让我们看一个示例拓扑。

假设您的拓扑变为 spout -> bolt1,并且您正在从 spout 发出 MyObject 实例。

假设您已将拓扑设置为在 1 个工作人员中运行。

当从 spout 发出一个元组(例如 MyObject@1234)时,Storm 将检查该元组是否需要转到另一个工作人员。如果没有,它只是将对象引用传递给bolt1。这就是您只有 1 个工人时所看到的。当 MyObject@1234 需要从 spout 转移到 bolt 时,Storm 只是将 MyObject@1234 引用交给 bolt。

现在假设你告诉拓扑使用 2 个 worker,Storm 决定将 spout 放在 worker 1 中,将 bolt 放在 worker 2 中。回想一下,每个 worker 都是一个单独的 JVM 进程,因此将对象引用从 worker 1 传递给 worker 2不会工作。

当元组从 spout 发出时,Storm 会看到它正在发送给另一个工作人员,并根据您的配置使用 Kryo 或 Java 序列化对其进行序列化。这意味着 MyObject@1234 被序列化。Storm 将序列化的表单交给 worker 2,后者将其反序列化。当它被反序列化时,它被非常合理地赋予了一个新的内存地址(例如MyObject@6789)。

如果您设计螺栓以假设它们不在同一个 JVM 中运行,这不是问题,您绝对应该这样做。例如,如果您想将 MyObject 从 worker 1 传输到 worker 2,您可以将其设为 Serializable,或者您可以将其注册到 Kryo(参见https://storm.apache.org/releases/2.0.0-快照/序列化.html )。您需要这样做,以便 Storm 可以将您的 spout 和 bolts 放在单独的 JVM 中,而不会破坏您的拓扑。

测试拓扑时,应启用https://storm.apache.org/releases/1.2.2/javadocs/org/apache/storm/Config.html#TOPOLOGY_TESTING_ALWAYS_TRY_SERIALIZE。这将导致 Storm 始终序列化您的元组,即使元组没有在工作人员之间传输。这可以帮助您在序列化问题投入生产之前发现它们。

顺便说一句,您应该始终更喜欢 Kryo 序列化而不是 Java 序列化。Kryo 序列化要快得多。

于 2019-01-14T21:25:59.157 回答