风暴>如何将Java回调集成到Spout中

时间:2013-04-02 17:41:12

标签: clojure streaming message-queue apache-storm

我正在尝试将Storm(see here)集成到我的项目中。我理解了拓扑,喷口和螺栓的概念。但是现在,我正在试图找出一些事情的实际实现。

A)我有一个带有Java和Clojure的多语言环境。我的Java代码是一个回调类,其中包含触发流数据的方法。推送到这些方法的事件数据是我想用作喷口的。

所以第一个问题是如何将进入这些方法的数据连接到spout?我正在尝试 i)传递 backtype.storm.topology.IRichSpout ,然后 ii)传递 backtype.storm。 spout.SpoutOutputCollector see here)到该spout的 open 函数(see here)。但我无法看到实际传递任何类型的地图或列表的方法。

B)我项目的其余部分都是Clojure。通过这些方法将会有大量数据。每个事件的ID都在1到100之间。在Clojure中,我想将来自spout的数据拆分为不同的执行线程。我认为那些将是螺栓。

如何设置Clojure螺栓以从喷口中获取事件数据,然后根据传入事件的ID中断线程?

提前致谢 添

[编辑1]

我实际上已经解决了这个问题。我最终 1)实现了我自己的IRichSpout。然后我 2)将spout的内部元组连接到我的java回调类中的传入流数据。我不确定这是不是惯用的。但它编译并运行没有错误。但是, 3)我没有看到传入的流数据(肯定存在),通过 printstuff 螺栓。

为了确保事件数据得到传播,我是否需要在spout或bolt实现或拓扑定义中做些具体的事情?感谢。


      ;; tie Java callbacks to a Spout that I created
      (.setSpout java-callback ibspout)

      (storm/defbolt printstuff ["word"] [tuple collector]
        (println (str "printstuff --> tuple["tuple"] > collector["collector"]"))
      )
      (storm/topology
       { "1" (storm/spout-spec ibspout)
       }
       { "3" (storm/bolt-spec  { "1" :shuffle }
                               printstuff
             )
       })

[编辑2]

根据SO成员Ankur的建议,我正在重新调整我的拓扑结构。在我创建了Java回调之后,我使用(.setTuple ibspout (.getTuple java-callback))将它的元组传递给下面的IBSpout。我没有传递整个Java回调对象,因为我收到NotSerializable错误。一切都编译并运行没有错误。但同样,我的 printstuff 螺栓没有数据。嗯。


    public class IBSpout implements IRichSpout {

      /**
       * Storm spout stuff
       */
      private SpoutOutputCollector _collector;

      private List _tuple = new ArrayList();
      public void setTuple(List tuple) { _tuple = tuple; }
      public List getTuple() { return _tuple; }

      /**
       * Storm ISpout interface functions
       */
      public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
        _collector = collector;
      }
      public void close() {}
      public void activate() {}
      public void deactivate() {}
      public void nextTuple() {
        _collector.emit(_tuple);
      }
      public void ack(Object msgId) {}
      public void fail(Object msgId) {}


      public void declareOutputFields(OutputFieldsDeclarer declarer) {}
      public java.util.Map  getComponentConfiguration() { return new HashMap(); }

    }

2 个答案:

答案 0 :(得分:3)

似乎你正在将spout传递给你的回调类,这看起来有点奇怪。执行拓扑时,storm会定期调用spouts nextTuple方法,因此你需要做的是将java回调传递给你的自定义spout实现,这样当storm调用你的spout时,spout会调用java回调来获取下一组要加入拓扑的元组。

要理解的关键概念是,当风暴请求时,Spouts 数据,不会将数据推送到spouts。你的回调不能调用spout将数据推送到它,而是当你的spout的nextTuple方法被调用时,你的spout应该从(从某些java方法或任何内存缓冲区)中提取数据。

答案 1 :(得分:0)

回答B部分:

直截了当的回答听起来像是在寻找一个字段分组,这样你就可以控制在ID执行期间将哪些工作组合在一起。

那就是说,我不相信这是一个完整的答案,因为我不知道你为什么要这样做。如果您只想要一个平衡的工作负载,那么随机分组是更好的选择。