多线程风暴螺栓并行

时间:2016-04-20 04:55:40

标签: multithreading apache-kafka apache-storm

测试组件

从机器读取文件的

Kafka Procucer ,文件由1000行组成。

        String sCurrentLine;
        br = new BufferedReader(new FileReader("D:\\jsonLogTest.txt"));
        while ((sCurrentLine = br.readLine()) != null) {
            //System.out.println(sCurrentLine);
            KeyedMessage<String, String> message =new KeyedMessage<String, String>(TOPIC,sCurrentLine);
            producer.send(message);
        }   
具有三个螺栓的

风暴消费者,BoltOne应该接收流并将其划分为两个不同的Streams(Stream1&amp; Stream2)。 BoltTwo和BoltThree应订阅这些Streams。 (简单来说,我希望在BoltOne parley中处理元组,如Bolt2处理前500行和BolltThree处理500行。

拓扑

builder.setSpout("line-reader-spout",kafkaSpout,1);
        builder.setBolt("bolt-one", new BoltOne(),1).shuffleGrouping("line-reader-spout");
        builder.setBolt("bolt-two", new BoltTwo(),1).shuffleGrouping("bolt-one","stream1");
        builder.setBolt("bolt-three", new BoltThree(),1).shuffleGrouping("bolt-one","stream2");

BoltOne

collector.emit("stream1", new Values(input.getString(0)));
            collector.emit("stream2", new Values(input.getString(0)));
        x++;System.out.println("" + x);
        collector.ack(input);

public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
        // TODO Auto-generated method stub
        outputFieldsDeclarer.declareStream("stream1", new Fields("field1"));
        outputFieldsDeclarer.declareStream("stream2", new Fields("field2"));
    }

BoltTwo&amp; BoltThree

public void execute(Tuple input) {
        String sentence = input.getString(0);
        System.out.println("*********B2*************");

    }

栈跟踪

*********B2*************
1
*********B3*************
2
*********B2*************
*********B3*************
3
*********B3*************
*********B2*************
4
*********B3*************
*********B2*************
5
*********B2*************
*********B3*************
6
*********B2*************
*********B3*************
7
*********B3*************
*********B2*************

与分裂流和并行性完全混淆。示例会有所帮助。

更新了解决方案我现在想出来了:

public void execute(Tuple input) {
        @SuppressWarnings("unused")
        String sentence = input.getString(0);
        if (x%2==0) {
            collector.emit("stream1", new Values(input.getString(0)));
        }
        else{
            collector.emit("stream2", new Values(input.getString(0)));
        }

        x++;
        collector.ack(input);
    }

我只是在偶数奇数的基础上划分了流,并且处理的时间变成了一半,而BoltTwo处理了一个元组,其他由BoltThree处理。

1 个答案:

答案 0 :(得分:0)

我猜你用LocalCluster运行一切。由于有多个线程正在运行,因此println(...)的输出不会同步,内部缓冲会使输出的顺序搞乱......因此,您看到的内容不可靠 - 订单仅保留在单嘴/螺栓。

此外,您想要获得的行为是什么?

现在,你有

Spout => Bolt1 =+=> Bolt2
                +=> Bolt3

即,Bolt1的输出是重复的,Bolt2和Bolt3都接收来自Bolt1的所有输出元组。因此,Bolt1从1到7计数,Bolt1的每个输出元组触发Bolt2和Bolt3的execute()

由于Bolt2和Bolt3做同样的事情,我想你想拥有相同Bolt的两个副本并将输入分区到两者。为此,您只需添加一个螺栓并将并行度设置为2:

builder.setSpout("line-reader-spout",kafkaSpout,1);
builder.setBolt("bolt-one", new BoltOne(),1).shuffleGrouping("line-reader-spout");
builder.setBolt("bolt-two", new BoltTwo(),2).shuffleGrouping("bolt-one","stream1");

此外,Bolt1只需要声明一个输出流(而不是两个)。如果声明多个输出流并写入两者,则复制数据...