storm(五) 消息分组策略

  • 消息分发策略决定了消息在spout和bolt间,bolt和bolt间如何进行传递。决定tuple传递给哪个bolt

grouping

http://storm.apache.org/releases/1.2.2/Concepts.html

  • 流分组策略有内置的八种,同时还可以进行自定义。这里将介绍最常用的几种
  • 流分组策略主要针对的是多个相同种类的bolt,哪个或那几个bolt实例接受消息

Shuffle grouping

  • 随机分发到两个bolt上,确保两个bolt上tuple的数量大体相同,从日志打印上可看出。
builder.setSpout("createNum",new NumSpout(),1);
builder.setBolt("countNum",new SumBolt(),2)
        .shuffleGrouping("createNum");

Fields grouping

  • 按照特定字段来进行分发,保证相同的字段分发到同一个bolt上。
  • 配置grouping:
 builder.setSpout("createNum",new NumSpout(),1);
 builder.setBolt("countNum",new SumBolt(),2)
         .fieldsGrouping("createNum",new Fields("isOdd"));//按照isOdd进行分区
		 .fieldsGrouping( ConstData.CACHE_BOLT, ConstData.PROCESSOR_STREAM, new Fields( AlarmAttrName.ME ) )//定义流
  • 由于是按照特定的field进行分发,所以需要在额外添加一个isOdd字段用来分发:
public class NumSpout extends BaseRichSpout{
    private SpoutOutputCollector collector;
    private Integer number=0;
    public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
        this.collector=collector;
    }
    public void nextTuple() {
        int num=++number;
        //发射的值带上用于分发的字段
        collector.emit(Arrays.asList((Object)num,num%3));
        System.out.println("number:"+number);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public void declareOutputFields(OutputFieldsDeclarer declarer) {
        declarer.declare(new Fields("num","isOdd"));//声明发出的字段分别是num和isOdd
    }
}

All Grouping

  • 数据会传给所有的bolt上,换句话说数据可能会被重复执行
 builder.setSpout("createNum",new NumSpout(),1);
 builder.setBolt("countNum",new SumBolt(),2)
         .allGrouping("createNum");

direct grouping

https://blog.csdn.net/simon_09010817/article/details/81364357

  • 将数据定向发送到一个指定的bolt上(由发送者决定目标bolt)
public class NumSpout extends BaseRichSpout{

    private SpoutOutputCollector collector;
    private Integer number=0;
    private List<Integer> idList;

    public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
        this.collector=collector;
        //根据componentId(bolt或者是spout)获取所有的task id
        this.idList=context.getComponentTasks("countNum");
    }

    public void nextTuple() {
        int num=++number;
        //将消息发送到指定的task id上
        collector.emitDirect(idList.get(1),new Values(num));
        System.out.println("number:"+number);

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void declareOutputFields(OutputFieldsDeclarer declarer) {
        declarer.declare(new Fields("num"));
    }
}
builder.setSpout("createNum",new NumSpout(),1);
builder.setBolt("countNum",new SumBolt(),3)
        .directGrouping("createNum");

Stream

  • 每个stream都有一个唯一的id,如果不指定将为default。通过stream id可以定义不同流数据的去向
  • 在设置数据来源的时候需要填写两个字段:component id和stream id(可以不填,默认是DEFAULT_STREAM_ID)
    • 定义流(在定义TopoLogy的时候定义):builder.setBolt("splitBolt",new SplitBolt()).shuffleGrouping("readWrite","stream id");
    • 按照流来进行分发:this.collector.emit("stream id",input,new Values(word));
    • 申明输出字段:declarer.declareStream("stream id", new Fields("word"));
  • 通过不同的流id,可以将tuple分发到不同种类的bolt

你可能感兴趣的:(storm)