【发布时间】:2016-06-30 22:14:18
【问题描述】:
几周以来,我们在项目中使用了 Storm。今天,我们发现了一个非常奇怪的行为。 假设我们有以下拓扑:
SpoutA ---> BoltB
---> BoltC
所以,我们有一个 SpoutA,它向两个不同的 Bolt 发出一个自定义 Java 对象(我们称之为消息)。 BoltB 和 BoltC。基本上,我们执行拆分。
直到今天,我们还假设如果 SpoutA 发出消息对象,它会在 SpoutA 上序列化,并在 BoltB 和 BoltC 上反序列化。然而,这个假设似乎是错误的。今天,我们发现 BoltB 中的反序列化对象与 BoltC 中的对象完全相同(Same System.identitfyHashCode)。换句话说,如果我在 BoltB 中操作 Object,我也在 BoltC 中操作 Object,从而导致许多无法预料的副作用。
此外,这种行为对我来说似乎很奇怪,因为它仅适用于 SpoutA 和相应的 Bolts B 和 C 在同一个 worker 中运行的情况。如果我明确强制使用三个作品,那么该对象(如预期的那样)是 BoltB 和 BoltC 的不同对象,因为它用于不同的 JVM。因此,如果我们假设我们有一个更大的拓扑(50 个不同的螺栓)在三个工人上运行,那么我们永远无法确定对象当前是否在螺栓之间共享。
所以基本上,我们真的不希望一个对象在螺栓之间共享。我们通常期望在反序列化期间,为每个螺栓创建新的不同对象。
所以这是我的问题: 我们这里的主要缺陷是什么?我们发出“可变”对象是我们的主要缺陷吗?我们是否使用了错误的序列化/反序列化?或者它甚至可能是风暴的设计缺陷?
显然,我们可以通过发出字节数组来强制创建新对象,但在我看来这与 Storm 相矛盾。
最好的问候, 安德烈
【问题讨论】:
-
目前我们正在生产中运行 40 螺栓风暴进程,最初我们遇到了更棘手的问题,因此当我们将对象从一个螺栓解析到另一个螺栓时,我们使用 xml 序列化,它将作为 xml 字符串传递。它解决了我们的问题
-
是的,我们还考虑过实现我们自己的序列化/反序列化(但随后在字节级别)。另一种解决方案是按照约定将传输的对象明确定义为不可变的。但是,我希望可能有更好的解决方案(例如,只是一个强制风暴分别反序列化对象的设置......)
-
是的,您可以将这些汇总到选项中
标签: java apache-storm mutable