几个星期以来,我们在项目中使用了storm。今天,我们发现了一个非常奇怪的行为。假设我们有以下拓扑结构:
SpoutA ---> BoltB
---> BoltC
因此,我们有一个spouta,它向两个不同的螺栓发出一个自定义java对象(我们称之为message)。螺栓B和螺栓C。基本上,我们进行分裂。
到今天为止,我们一直假设,如果spouta发出消息对象,它将在spouta上序列化,并在boltb和boltc上反序列化。然而,这种假设似乎是错误的。今天,我们发现boltb中的反序列化对象与boltc中的对象完全相同(system.identitfyhashcode相同)。换句话说,如果我操纵boltb中的对象,我也操纵boltc中的对象,导致许多无法预料的副作用。
此外,这种行为对我来说似乎非常奇怪,因为它只适用于喷口和相应的螺栓b和c在同一个工作台上运行的情况。如果我显式地强制使用三个works,那么这个对象(正如预期的那样)对于boltb和boltc是不同的对象,因为它在不同的jvm中使用。因此,如果我们假设有一个更大的拓扑(50个不同的螺栓)在三个worker上运行,那么我们永远无法确定对象当前是否在螺栓之间共享。
所以基本上,我们真的不希望螺栓之间共享一个对象。我们通常希望在反序列化过程中,为每个螺栓创建新的不同对象。
所以我的问题是:我们的主要缺点是什么?我们发射“可变”物体的主要缺陷是什么?我们使用序列化/反序列化错误吗?或者这可能是暴风雪的设计缺陷?
显然,我们可以通过发射字节数组来强制创建新对象,但在我看来,这与storm是矛盾的。
祝你好运,安德烈é
2条答案
按热度按时间57hvy0tb1#
为什么您希望hashcode是不同的?就像没有要求每个新对象示例的用户提供的hashcode值应该不同一样(具有相同的字段和字段值!),没有什么要求本机hashcode实现在创建同一对象两次时返回不同的值。
那么回答你的问题:我们的主要缺陷是什么?
主要的缺陷是您对hashcode工作原理的理解。正如maheshmadushanka在评论中指出的,您可以绕过这个特性。
当你序列化一个对象时,它也会序列化所有的内容,包括私有字段。许多java对象将它们的散列值缓存在私有字段中。e、 g.字符串。因此,它们的hashcode将返回相同的值是完全正常的(我知道您使用system.identitfyhashcode,string将返回重写的值,但记住这一点很重要)。
zzwlnbp82#
storm在将元组从一个组件移动到另一个组件时使用两种不同的排队方法,一种是两个组件在同一个jvm中,另一种是元组必须跨jvm移动。我认为您正陷入同一个jvm案例中,元组中的对象实际上并没有序列化,因为序列化只是跨jvm队列需要的。
我总是对tuple和javabean之间的数据进行marshall和demarshall,以便在每个bolt/spout中为我的业务逻辑提供一个强类型接口。这样做,我想我无意中避免了你碰到的问题。这可能是解决你问题的一种方法。