我是不熟悉Apache风暴的人,我编写了包含1个喷口和2个螺栓的代码,当我在一个工作程序上运行这3个零件时,代码会正确生成输出,但是当我在三个工作程序上运行代码时,一名工人执行喷水嘴,另一只执行螺栓1和最后一个执行螺栓2,将不会生成输出。 具体情况:当我将螺栓1和2放在一个工人中时,就会产生输出!
我不得不说,发射工作成功,并且发射变量没有问题。
详细信息:我在螺栓1中以哈希图结构创建了树,我想在螺栓2中挖掘此树。在螺栓1中的树中插入的对象的ID类似于“ MyTreeNode @ e70014d5”,当我收到此消息时螺栓2中的元组(哈希图),id更改为类似“ MyTreeNode @ z5542r12”的内容。
主要问题是什么?
是由于对象ID更改引起的问题吗?如果是,请您告诉我该如何解决?
答案 0 :(得分:0)
让我们看一个示例拓扑。
假设您的拓扑结构为出水嘴-> bolt1,并且您正在从出水嘴发出MyObject实例。
假设您已将拓扑设置为可以在1个工作进程中运行。
当从喷嘴喷出一个元组(例如MyObject @ 1234)时,Storm将检查该元组是否需要转到其他工作人员。如果没有,它只是将对象引用传递给bolt1。这是您只有1个工人时看到的。当MyObject @ 1234需要从喷嘴转移到螺栓时,Storm只需将螺栓交给MyObject @ 1234参考。
现在,假设您告诉拓扑使用2个工作线程,Storm决定将喷口放入工作线程1,将螺栓放入工作线程2。回想一下,每个工作线程都是一个单独的JVM进程,因此从工作线程1传递对象引用对工人2无效。
当从喷嘴中发出元组时,Storm会看到它要去往另一个工作程序,并根据您的配置使用Kryo或Java序列化对其进行序列化。这意味着MyObject @ 1234被序列化。 Storm将序列化的表格交给工作人员2,该工作人员对其进行反序列化。反序列化时,将非常合理地为其分配一个新的内存地址(例如MyObject @ 6789)。
如果您设计螺栓以假定它们不在同一JVM中运行,那么这不是问题,您绝对应该这样做。例如,如果要将MyObject从工作程序1传输到工作程序2,则可以将其设置为可序列化,也可以在Kryo中进行注册(请参见https://storm.apache.org/releases/2.0.0-SNAPSHOT/Serialization.html中的操作)。您需要执行此操作,以便Storm可以将喷口和螺栓放在单独的JVM中,而不会破坏拓扑。
在测试拓扑时,应启用https://storm.apache.org/releases/1.2.2/javadocs/org/apache/storm/Config.html#TOPOLOGY_TESTING_ALWAYS_TRY_SERIALIZE。这将使Storm始终对您的元组进行序列化,即使该元组不在工作人员之间进行转移也是如此。这可以帮助您在序列化投入生产之前就发现问题。
顺便说一句,您应该始终喜欢Kryo序列化而不是Java序列化。 Kryo序列化要快得多。