运行 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 项目的一部分,我正在尝试将第一个Spout中的Object类型 Event 传输到第一个Bolt,然后再使用它。 不幸的是,在我的配置变量中实现所有需要的更改和提交后 - 如 Storm 文档中所述,它仍然无法反序列化一个类型为“GUID”的私有字段,这是我自己的私有字段中的一个字段class 事件。
我创建了以下序列化类:
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);
答案 0 :(得分:2)
用作属性/字段的数据类型的所有类必须实现Java的Serializable
接口。在您的情况下,这适用于您的Event
课程以及Event
的所有使用成员,例如GUID
。当然,这是递归应用的,即如果GUID
包含自定义类型,那么它们也必须实现Serializable
。
提供自定义Kryo序列化程序实际上不是必需的。 Storm可以使用Java的默认序列化程序。但是出于性能原因,强烈建议注册自定义类型。在大多数情况下,通过
简单注册用户类型类就足够了conf.registerSerialization(MyUserType.class);
在你的情况下
conf.registerSerialization(Event.class);
conf.registerSerialization(GUID.class);
注册类允许Storm使用更高效(通用)的Kryo序列化程序而不是Java的默认序列化程序。
如果这个通用的Kryo序列化程序仍然不够高效,你可以提供一个自己的Kryo序列化程序(正如你在问题中提到的那样)。 但是,该类仍必须实现Java的Serializable
接口!
答案 1 :(得分:1)
我不知道Serializer
课程,但从异常情况来看,您需要让GUID
课程实现Interface java.io.Serializable
,如:
public class GUID implements Serializable {
//...
如有疑问,请发布GUID
的当前代码。