java - Apache Storm : Mutable Object emitted to different bolts

标签 java apache-storm mutable

几周以来,我们在项目中使用了 Storm。今天,我们发现了一个非常奇怪的行为。 假设我们有以下拓扑:


SpoutA ---> BoltB
       ---> BoltC 

因此,我们有一个 SpoutA,它向两个不同的 Bolt 发出自定义 Java 对象(我们称之为消息)。 bolt B 和 bolt C。基本上,我们执行拆分。

直到今天,我们假设如果 SpoutA 发出消息对象,它会在 SpoutA 上序列化并在 BoltB 和 BoltC 上反序列化。然而,这个假设似乎是错误的。今天,我们发现BoltB中的反序列化对象与BoltC中的对象完全相同(Same System.identitfyHashCode)。换句话说,如果我操作了BoltB中的Object,我也操作了BoltC中的Object,导致许多不可预见的副作用。

此外,这种行为对我来说似乎很奇怪,因为它只适用于 SpoutA 和相应的 Bolt B 和 C 在同一个 worker 中运行的情况。如果我明确强制使用三个作品,那么该对象(正如预期的那样)是 BoltB 和 BoltC 的不同对象,因为它用于不同的 JVM。因此,如果我们假设我们有一个更大的拓扑(50 个不同的 bolts)在三个 worker 上运行,那么我们永远无法确定对象当前是否在 bolts 之间共享。

所以基本上,我们真的不希望在 bolt 之间共享一个对象。我们通常期望在反序列化过程中,为每个 bolt 创建新的不同对象。

所以这是我的问题: 我们这里的主要缺陷是什么?我们发出“可变”对象是我们的主要缺陷吗?我们使用序列化/反序列化错误吗?或者它甚至可能是 Storm 的设计缺陷?

显然,我们可以通过仅发出字节数组来强制创建新对象,但我认为这与 Storm 相矛盾。

最好的问候, 安德烈

最佳答案

Storm 在将元组从一个组件移动到另一个组件时使用两种不同的排队方法,一种是两个组件位于同一 JVM 内,另一种是元组必须跨 JVM 传输。我认为您陷入了同一个 JVM 的情况,其中元组中的对象实际上并未序列化,因为只有跨 JVM 队列才需要序列化。

我总是对元组和 Java bean 之间的数据进行编码和解码,以便在每个 bolt/spout 中为我的业务逻辑提供强类型接口(interface)。这样做我想我无意中避免了你遇到的问题。这可能是解决您的问题的一种方法。

关于java - Apache Storm : Mutable Object emitted to different bolts,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38105443/

相关文章:

java - NoClassDefFound错误: Maven intermodule dependency

c++ - C++ 中可变的动机

python - 将 Pandas DataFrame 传递给函数的最佳实践

java - 如何在tomcat中部署一个eclipse动态网页?

apache-storm - Storm 支持类似批处理的处理

java - NetBeans 停止在 NetBeans 重构代码中强调错误

apache-storm - Storm 杀死的拓扑未从拓扑列表中删除

java - 使用 B-Tree 索引 <String, Arraylist<Integer>>

java - 我需要从列表标签内的 json 脚本获取数据

java - 私有(private) JVM 上的 Spring boot ware 部署,无法访问 Controller