《Storm企業級應用:實戰、運維和調優》——2.4 建立Topology並向叢集提交任務

華章計算機發表於2017-07-03

本節書摘來自華章計算機《Storm企業級應用:實戰、運維和調優》一書中的第2章,第2.4節,作者:馬延輝 陳書美 雷葆華著, 更多章節內容可以訪問雲棲社群“華章計算機”公眾號檢視。

2.4 建立Topology並向叢集提交任務

Topology是Storm的核心概念之一,是將Spout與Bolt融合在一起的紐帶,在Storm叢集中執行,完成實時計算的任務。在Storm叢集中,Topology的定義是一個Thrift結構,並且Nimbus就是一個Thrift服務,可以提交由任何語言建立的Topology。下面使用Java語言講解Topology的使用。首先了解如何建立Topology。
2.4.1 建立Topology
在建立一個Topology之前,設計一個Topology來統計詞頻。在建立Topology之前,要準備Spout(資料來源)和Bolt來組成Topology。這裡簡單介紹建立的Spout和Bolt,第3章會詳細介紹這兩個概念。
下面梳理Topology的大致結構。
1.?Spout
建立一個WordSpout資料來源,負責傳送語句。WordSpout的程式碼如下:

public class WordSpout extends BaseRichSpout {
    private SpoutOutputCollector collector;
    private static f?inal String[] msgs = new String[] {
             "I have a dream",
             "my dream is to be a data analyst",
             "you kan do what you are dreaming",
             "don`t give up your dreams",
             "it`s just so so ",
             "We need change the traditional ideas and practice boldly",
             "Storm enterprise real time calculation of actual combat",
             "you kan be what you want be",
             };
    private static f?inal Random random = new Random();   
    public void open(Map conf, TopologyContext context,
             SpoutOutputCollector collector) {
        this.collector = collector;
    }

    public void nextTuple() {
        String sentence= msgs[random.nextInt(8)];
        collector.emit(new Values(sentence));
    }

    public void declareOutputFields(OutputFieldsDeclarer declarer) {
        declarer.declare(new Fields("sentence"));
    }
  }

2.?Bolt
兩個Bolt,一個負責將語句切分,即SplitSentenceBolt,另一個是對切分的單詞進行詞頻累加的Bolt,即WordCountBolt。下面是這兩個Bolt的具體程式碼。

public class SplitSentenceBolt implements IBasicBolt{ 
      public void prepare(Map conf, TopologyContext context) { 
       } 
      public void execute(Tuple tuple, BasicOutputCollector collector) { 
            String sentence = tuple.getString(0); 
             for(String word: sentence.split(" ")) { 
                     collector.emit(new Values(word)); 
               } 
         } 
      public void cleanup() { 
      } 
      public void declareOutputFields(OutputFieldsDeclarer declarer) { 
            declarer.declare(new Fields("word")); 
          } 
 } 
public class WordCountBolt implements IBasicBolt { 
      private Map<String, Integer> _counts = new HashMap<String, Integer>(); 
      public void prepare(Map conf, TopologyContext context) { 
      } 
      public void execute(Tuple tuple, BasicOutputCollector collector) { 
            String word = tuple.getString(0); 
            int count; 
            if(_counts.containsKey(word)) { 
                count = _counts.get(word); 
            } else { 
                count = 0; 
} 
            count++; 
            _counts.put(word, count); 
            collector.emit(new Values(word, count)); 
      } 
      public void cleanup() { 
      } 
      public void declareOutputFields(OutputFieldsDeclarer declarer) { 
            declarer.declare(new Fields("word", "count")); 
      }
}

3.?Topology
要建立的Topology的Spout從句子佇列中隨機生成一個句子,Spout用setSpout方法插入一個獨特的ID到Topology。必須給予Topology中的每個節點一個ID,ID是由其他Bolt用於訂閱該節點的輸出流,其中WordSpout在Topology中的ID為1。
setBolt用於在Topology中插入Bolt,在Topology中定義的第一個Bolt是切分句子的SplitSentenceBolt,該Bolt將句子流轉成單詞流,第二個Bolt統計單詞。Topology的程式碼如下:

TopologyBuilder builder = new TopologyBuilder(); 
bulider.setSpout(1,new WordSpout(),2);
builder.setBolt(2, new SplitSentenceBolt(), 10).shuffleGrouping(1); 
builder.setBolt(3, new WordCountBolt(), 20).f?ieldsGrouping(2, new Fields("word"));

這樣就建立了簡單的Topology結構,下面介紹如何使用Topology。
2.4.2 向叢集提交任務
向Storm叢集提交Topology任務,類似提交MapReduce作業到Hadoop叢集中,只需要執行JAR包中的Topology即可。而使用kill命令可以殺掉任務,類似殺掉MapReduce作業。下面詳細介紹這兩部分內容。
1.?啟動Topology
在Storm的安裝主目錄下,執行下面的命令提交任務:

bin/storm jar testTopolgoy.jar org.me.MyTopology arg1 arg2 arg3

其中,jar命令專門負責提交任務,testTopolgoy.jar是包含Topology實現程式碼的JAR包,org.me.MyTopology的main方法是Topology的入口,arg1、arg2和arg3為org.me.MyTopology執行時需要傳入的引數。
2.?停止Topology
在Storm主目錄下,執行kill命令停止之前已經提交的Topology:

bin/Storm kill {toponame}

其中,{toponame}為Topology提交到Storm叢集時指定的Topology任務名稱,該名稱可以在程式碼中指定,也可以作為引數傳入Topology中。


相關文章