如何在Storm拓扑中序列化非基本类型(您自己的类)的字段?

时间:2015-11-03 17:02:17

标签: java serialization apache-storm kryo

运行 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);

2 个答案:

答案 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的当前代码。