Java 在简单聚合风暴拓扑中分组

Java 在简单聚合风暴拓扑中分组,java,apache-storm,Java,Apache Storm,我正在尝试编写一个拓扑,它可以执行以下操作: 订阅推特提要的喷口(基于关键字) 一种聚合螺栓,用于聚合集合中的大量tweet(例如N),并将其发送到打印机螺栓 一个简单的插销,可以立即将集合打印到控制台 实际上,我想对收集的内容做更多的处理 我在本地测试了它,看起来它正在工作。但是,我不确定我是否正确地设置了螺栓上的分组,以及在实际风暴集群上部署时是否可以正常工作。如果有人能帮我查看这个拓扑结构,并提出任何错误、更改或改进建议,我将不胜感激 谢谢 这就是我的拓扑结构 builder.setSpo

我正在尝试编写一个拓扑,它可以执行以下操作:

  • 订阅推特提要的喷口(基于关键字)
  • 一种聚合螺栓,用于聚合集合中的大量tweet(例如N),并将其发送到打印机螺栓
  • 一个简单的插销,可以立即将集合打印到控制台 实际上,我想对收集的内容做更多的处理

    我在本地测试了它,看起来它正在工作。但是,我不确定我是否正确地设置了螺栓上的分组,以及在实际风暴集群上部署时是否可以正常工作。如果有人能帮我查看这个拓扑结构,并提出任何错误、更改或改进建议,我将不胜感激

    谢谢

    这就是我的拓扑结构

    builder.setSpout("spout", new TwitterFilterSpout("pittsburgh"));
       builder.setBolt("sampleaggregate", new SampleAggregatorBolt())
                    .shuffleGrouping("spout");
       builder.setBolt("printaggreator",new PrinterBolt()).shuffleGrouping("sampleaggregate");
    
    聚合螺栓

    public class SampleAggregatorBolt implements IRichBolt {
    
        protected OutputCollector collector;
        protected Tuple currentTuple;
        protected Logger log;
        /**
         * Holds the messages in the bolt till you are ready to send them out
         */
        protected List<Status> statusCache;
    
        @Override
        public void prepare(Map stormConf, TopologyContext context,
                            OutputCollector collector) {
            this.collector = collector;
    
            log = Logger.getLogger(getClass().getName());
            statusCache = new ArrayList<Status>();
        }
    
        @Override
        public void execute(Tuple tuple) {
            currentTuple = tuple;
    
            Status currentStatus = null;
            try {
                currentStatus = (Status) tuple.getValue(0);
            } catch (ClassCastException e) {
            }
            if (currentStatus != null) {
    
                //add it to the status cache
                statusCache.add(currentStatus);
                collector.ack(tuple);
    
    
                //check the size of the status cache and pass it to the next stage if you have enough messages to emit
                if (statusCache.size() > 10) {
                    collector.emit(new Values(statusCache));
                }
    
            }
        }
    
        @Override
        public void cleanup() {
    
    
        }
    
        @Override
        public void declareOutputFields(OutputFieldsDeclarer declarer) {
            declarer.declare(new Fields("tweets"));
    
        }
    
        @Override
        public Map<String, Object> getComponentConfiguration() {
            return null;  //To change body of implemented methods use File | Settings | File Templates.
        }
    
    
        protected void setupNonSerializableAttributes() {
    
        }
    
    }
    

    从我看来,它看起来不错。然而,魔鬼在细节中。我不知道你的聚合器螺栓是做什么的,但是如果它对传递给它的值做任何假设,那么你应该考虑一个适当的字段分组。这可能不会有太大的区别,因为您使用的是默认的并行提示1,但如果您决定使用多个聚合螺栓实例进行扩展,您所做的隐式逻辑假设可能会要求使用非随机分组。

    嗨,一旦您尝试订阅多个关键字,您就会遇到问题。我建议您的喷口也会发出用于过滤的原始关键字

    然后,我会做一个字段分组,而不是进行随机分组

    builder.setBolt("sampleaggregate", new SampleAggregatorBolt())
                .shuffleGrouping("spout", new Fields("keyword"));
    

    通过这种方式,您可以确保每次单个关键字的结果都出现在同一个螺栓上。这样您就可以正确地计算聚合。如果省略字段,则分组风暴可以实例化任意数量的聚合螺栓,并将任何消息从喷嘴发送到聚合螺栓的任何实例,这最终会导致错误的结果。

    我已提供了上述聚合螺栓的代码(请参见执行方法)。现在,它一直在等待,直到它积累了N条(在上面的例子中是10条)消息,并在它有10条消息时将它们分离出来。顺便说一句,我刚刚发现了一个我会修复的bug。我需要在发出值后清除缓存。所以,如果我需要使用多个聚合器,那么应该进行哪些更改。
    builder.setBolt("sampleaggregate", new SampleAggregatorBolt())
                .shuffleGrouping("spout", new Fields("keyword"));