Java Apache Storm Spout空反序列化LinkedList对象属性

时间:2015-11-05 15:31:52

标签: java serialization apache-storm

我有一个spout类,它有几个整数和字符串属性,按预期序列化/反序列化。该类还有1个LinkedList保存字节数组。当反序列化对象时,此LinkedList始终为空。

我已将日志语句添加到所有spout方法中,并且可以看到spout'激活'调用方法,之后,LinkedList为空。当发生这种情况时,我没有看到任何记录,以便停用'方法

喷口“激活”似乎很奇怪。在没有“停用”的情况下调用方法。被称为的方法。当'激活'调用方法时,没有重新提交拓扑。

我在spout构造函数中也有一个日志语句,它在清空LinkedList之前不会被调用。

我还反复验证,spout类中的任何地方都没有调用任何完全清空LinkedList的方法。有一个使用poll方法的点,后面紧跟一个日志语句来记录新的LinkedList大小。

我找到了这个引用,它指向Kryo用于序列化,但它可能仅用于序列化元组数据。 http://storm.apache.org/documentation/Serialization.html

  

Storm使用Kryo进行序列化。 Kryo是一个灵活而快速的人   生成小序列化的序列化库。

     

默认情况下,Storm可以序列化基本类型,字符串,字节数组,   ArrayList,HashMap,HashSet和Clojure集合类型。如果你   想要在你的元组中使用其他类型,你需要注册一个   自定义序列化器。

这篇文章听起来像Kryo可能只是用于序列化和传递元组,但如果它也适用于Spout对象,我无法弄清楚如何使用LinkedList作为ArrayLists和HashMaps并不是&# 39;对于FIFO队列来说,它确实是一个很好的选择。我是否必须滚动自己的LinkedList?

public class MySpout extends BaseRichSpout
{

    private SpoutOutputCollector _collector;
    private LinkedList<byte[]> messages = new LinkedList<byte[]>();

    public MyObject()
    {
        queue = new LinkedList<ObjectType>();
    }

    public void add(byte[] message)
    {
        messages.add(message);
    }

    @Override
    public void open( Map conf, TopologyContext context,
            SpoutOutputCollector collector )
    {
        _collector = collector;

        try
        {           
            Logger.getInstance().addMessage("Opening Spout");
            // ####### Open client connection here to read messages
        }
        catch (MqttException e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public void close()
    {
        Logger.getInstance().addMessage("Close Method Called!!!!!!!!!!!!!!!!!");
    }

    @Override
    public void activate()
    {
        Logger.getInstance().addMessage("Activate Method Called!!!!!!!!!!!!!!!!!");
    }

    @Override
    public void nextTuple()
    {

        if (!messages.isEmpty())
        {
            System.out.println("Tuple emitted from spout");            
            _collector.emit(new Values(messages.poll()));
            Logger.getInstance().addMessage("Tuple emitted from spout. Remaining in queue: " + messages.size());
            try
            {
                Thread.sleep(1);
            }
            catch (InterruptedException e)
            {
                // TODO Auto-generated catch block
                Logger.getInstance().addMessage("Sleep thread interrupted in nextTuple(). " + Logger.convertStacktraceToString(e));
                e.printStackTrace();
            }
        }
    }
}

编辑:

Java Serialization of referenced objects is "losing values"? http://www.javaspecialists.eu/archive/Issue088.html

上面的SO链接和java专家文章提出了类似于我所看到的具体示例,问题是进行序列化/反序列化缓存。但由于Storm正在开展这项工作,我不确定该怎么办。

在一天结束时,似乎更大的问题是Storm首先突然序列化/反序列化数据。

编辑:

在Spout被激活之前,在不到一秒的时间内就可以看到很多日志消息:

  

执行官MyTopology-1-1447093098:[X Y]不活着

在这些消息之后,有一个日志:

  

为拓扑ID设置新的分配MyTopology-1-1447093098:#backtype.storm.daemon.common.Assignment {:master-code-dir ...

1 个答案:

答案 0 :(得分:0)

如果我正确理解您的问题,您可以在客户端实例化您的spout,通过addMessage()添加消息,通过addSpout()将spout提供给TopologyBuilder,然后将拓扑提交到您的群集?拓扑启动时,您希望spout消息列表包含您添加的消息吗?如果这是正确的,你的使用模式很奇怪......

我猜这个问题与Thrift有关,Thrift用于将拓扑提交给集群。没有使用Java序列化,我假设,Thrift代码不会序列化实际对象。据我所知,代码中,拓扑jar是二进制的,拓扑 structure 是通过Thrift发布的。在执行拓扑的工作人员上,通过new创建新的spout / bolt对象。因此,不会发生Java序列化/反序列化,并且您的LinkedList为空。由于new的调用,它当然不是null

顺便说一下:你对Kryo说得对,它只用于发送数据(即元组)。

作为解决方法,您可以将LinkedList添加到Map的{​​{1}}。在StormSubmitter.submitTopology(...)中,您应该从Spout.open(...)参数中获取正确的邮件副本。但是,正如我已经提到的,你的使用模式很奇怪 - 你可能想重新考虑一下。通常,应该以某种方式实现spout,即可以从外部数据源获取Map中的数据。