storm中declareOutputFields方法的使用规则及与fieldsGrouping方法的联系

declareOutputFields方法中声明了该bolt/spout输出的字段个数,供下游使用,在该bolt中的execute方法中,emit发射的字段个数必须和声明的相同,否则报错:Tuple created with wrong number of fields. Expected 2 fields but got 1 fields。

        fieldsGrouping方法设定从上一个bolt中获取哪些fields。fieldsGrouping("2", new Fields("ahah","bb")),Fields中的参数名字必须和上一个bolt中声明的字段名字相同,否则报错:“Topology submission exception. (topology name='HelloStorm') #

测试Spout代码如下:

[java]  view plain  copy
  1. public class Produce extends BaseRichSpout {  
  2.     private SpoutOutputCollector collector;  
  3.     @Override  
  4.     public void nextTuple() {  
  5.         String[] str1=new String[]{"aaa","bbb","ccc","ddd"};  
  6.         String[] str2=new String[]{"ee","ff","gg","kk"};  
  7.         Random random=new Random();  
  8.         String word1=str1[random.nextInt(str1.length)];  
  9.         String word2=str2[random.nextInt(str2.length)];  
  10.         collector.emit(new Values(word1,word2));  
  11.         try {  
  12.             Thread.sleep(100);  
  13.         } catch (InterruptedException e) {  
  14.             e.printStackTrace();  
  15.         }  
  16.     }  
  17.   
  18.     @Override  
  19.     public void open(Map arg0, TopologyContext arg1, SpoutOutputCollector arg2) {  
  20.         this.collector=arg2;  
  21.     }  
  22.     @Override  
  23.     public void declareOutputFields(OutputFieldsDeclarer arg0) {  
  24.         arg0.declare(new Fields("ppee","ttt"));  
  25.     }  
  26. }  
测试Output代码如下:
[java]  view plain  copy
  1. public class Output extends BaseBasicBolt{  
  2.     @Override  
  3.     public void execute(Tuple tuple, BasicOutputCollector arg1) {  
  4.         String str=tuple.getString(0);  
  5.         String str1=tuple.getString(1);  
  6.         arg1.emit(new Values(str,str1));  
  7.         /*此处发射的字段个数必须要和declareOutputFields中声明的字段个数相同,否则报错: 
  8.          *  Tuple created with wrong number of fields. Expected 2 fields but got 1 fields 
  9.          */  
  10.     }  
  11.   
  12.     @Override  
  13.     public void declareOutputFields(OutputFieldsDeclarer arg0) {  
  14.         arg0.declare(new Fields("ahah","bb"));  
  15.     }  
  16. }  


测试writer代码如下:

[java]  view plain  copy
  1. public class Writer extends BaseBasicBolt{  
  2.   
  3.     @Override  
  4.     public void execute(Tuple arg0, BasicOutputCollector arg1) {  
  5.         // TODO Auto-generated method stub  
  6.         String str=arg0.getString(0);  
  7.         String str1=arg0.getString(1);  
  8.         System.out.println(str+"   "+str1+"  "+this);  
  9.     }  
  10.   
  11.     @Override  
  12.     public void prepare(Map stormConf, TopologyContext context) {  
  13.     }  
  14.   
  15.     @Override  
  16.     public void declareOutputFields(OutputFieldsDeclarer arg0) {  
  17.         arg0.declare(new Fields("hehe"));  
  18.     }  
  19. }  
测试Main类如下:
[java]  view plain  copy
  1. public class main {  
  2.   
  3.     public static void main(String[] args) throws Exception {  
  4.         TopologyBuilder builder=new TopologyBuilder();  
  5.         builder.setSpout("1"new Produce(),1);  
  6.         builder.setBolt("2"new Output(), 4).shuffleGrouping("1");  
  7.         builder.setBolt("3"new Writer(), 8).fieldsGrouping("2"new Fields("ahah","bb"));  
  8.         /*设定从上一个bolt中获取"ahah"字段,这个“ahah”必须要和上一个bolt中的declare声明的字段相同, 
  9.          * 否则报错,“Topology submission exception. (topology name='HelloStorm')  
  10.          * # 
  11.          * stream: [default] of component [2] with non-existent fields: #{"ahah1"})>” 
  12.          *  
  13.          */  
  14.           
  15.         Config con=new Config();  
  16.         con.setDebug(false);  
  17.         con.setNumWorkers(5);  
  18. //      StormSubmitter.submitTopology("first", con, builder.createTopology());  
  19.         LocalCluster cluster = new LocalCluster();  
  20.         cluster.submitTopology("HelloStorm", con, builder.createTopology());  
  21.     }  
  22. }  

    在运行测试的过程中发现一个有趣的现象,在builder.setBolt("3", new Writer(), 8).fieldsGrouping("2", new Fields("ahah","bb"))中的Fields中如果以第二个字段"bb"分组,则只打印出一个对象的哈希值,如果以第一个字段''ahah''或者两个字段则正常打印出多个对象的哈希值。《后续:经leader指导,是因为发射数据量的问题,发射数据改成"word+System.currentTimeMillis()",则按正常设置生成相应的Task对象》

    fieldsGrouping分组的含义是同id的tuple同时只能在一个Task上。

你可能感兴趣的:(storm)