当我运行我的 Storm 项目时抛出以下异常:
java.lang.RuntimeException: java.io.NotSerializableException: com.youtab.dataType.id.GUID
at backtype.storm.serialization.DefaultSerializationDelegate.serialize(DefaultSerializationDelegate.java:43)
at backtype.storm.utils.Utils.serialize(Utils.java:85)
at backtype.storm.topology.TopologyBuilder.createTopology(TopologyBuilder.java:111)
作为我的 Storm 项目的一部分,我尝试将对象类型 Event 从第一个 Spout 传输到第一个 Bolt,然后使用它。 不幸的是,在我的配置变量中实现了所有需要的更改和提交之后 - 如 Storm 文档中所述,它仍然无法反序列化“GUID”类型的一个私有(private)字段,该字段是我自己的私有(private)字段类事件。
我创建了以下序列化类:
public class GUIDSerializer extends Serializer<GUID> {
@Override
public void write(Kryo kryo, Output output, GUID guid) {
output.write(guid.toString().getBytes());
}
@Override
public GUID read(Kryo kryo, Input input, Class<GUID> aClass) {
return GUID.of(input.readString());
}
}
我根据需要注册了序列化:
Config conf = new Config();
conf.registerSerialization(GUID.class, GUIDSerializer.class);
最佳答案
用作属性/字段的数据类型的所有类都必须实现 Java 的 Serialized
接口(interface)。就您而言,这适用于您的 Event
类以及 Event
的所有使用的成员,例如 GUID
。当然,这是递归应用的,即,如果 GUID
包含自定义类型,那么它们也必须实现 Serialized
。
提供自定义 Kryo 序列化器实际上不需要。 Storm 可以使用 Java 的默认序列化器。但是,出于性能原因,强烈建议注册自定义类型。在大多数情况下,通过简单地注册用户类型类就足够了
conf.registerSerialization(MyUserType.class);
就你的情况
conf.registerSerialization(Event.class);
conf.registerSerialization(GUID.class);
注册一个类允许 Storm 使用更高效的(通用)Kryo 序列化器,而不是 Java 的默认序列化器。
如果这个通用的 Kryo 序列化器仍然不够高效,您可以提供自己的 Kryo 序列化器(正如您在问题中提到的)。 但是,该类仍然必须实现 Java 的 Serialized
接口(interface)!
关于java - 如何在 Storm 拓扑中序列化非原始类型(您自己的类)的字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33504989/