Storm - 大數據Big Data實時處理架構

什麼是Storm?

Storm是:
• 快速且可擴展伸縮
• 容錯
• 確保消息能夠被處理
• 易於設置和操作
• 開源的分佈式實時計算系統
- 最初由Nathan Marz開發
- 使用Java 和 Clojure 編寫

Storm和Hadoop主要區別是實時和批處理的區別:


Storm概念 組成:Spout 和Bolt組成Topology。

Tuple是Storm的數據模型,如['jdon',12346]

多個Tuple組成事件流:


Spout是讀取需要分析處理的數據源,然後轉爲Tuples,這些數據源可以是Web日誌、 API調用、數據庫等等。Spout相當於事件流的生產者。

Bolt 處理Tuples然後再創建新的Tuples流,Bolt相當於事件流的消費者。

Bolt 作爲真正業務處理者,主要實現大數據處理的核心功能,比如轉換數據,應用相應過濾器,計算和聚合數據(比如統計總和等等) 。

以Twitter的某個Tweet爲案例,看看Storm如何處理:



這些tweett貼內容是:“No Small Cell Lung #Cancer(沒有小細胞肺癌#癌症)” "An #OnCology Consult...."

這些貼被Spout讀取以後,產生Tuple,字段名是tweet,內容是"No Small Cell Lung #Cancer",格式類似:['No Small Cell Lung #Cancer',133221]。

然後進入被流 消費者Bolt進行處理,第一個Bolt是SplitSentence,將tuple內容進行分離,結果成爲:一個個單詞:"No" "Small" "Cell" "Lung" "#Cancer" ;然後經過第二個Bolt進行過濾HashTagFilter處理,Hash標籤是單詞中用#標註的,也就是Cancer;再經過HasTagCount計數,可以本地內存緩存這個計數結果,最後通過PrinterBolt打印出標籤單詞統計結果 。

我們使用Stom所要做的就是編制Spout和Bolt代碼:

public class RandomSentenceSpout extends BaseRichSpout {
  SpoutOutputCollector collector;
  Random random;

//讀入外部數據
  public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
    this.collector = collector;
    random = new Random();
  }
  //產生Tuple
   public void nextTuple() {
    String[] sentences = new String[] {
      "No Small Cell Lung #Cancer",
      "An #OnCology Consultant apple a day keeps the doctor away",
      "four score and seven years ago",
      "snow white and the seven dwarfs",
      "i am at two with nature"
    };
    String tweet = sentences[random.nextInt(sentences.length)];
    //定義字段名"tweet" 的值 
    collector.emit(new Values(tweet));

  }


// 定義字段名"tweet"

  public void declareOutputFields(OutputFieldsDeclarer declarer) {
    declarer.declare(new Fields("tweet"));
  }
  @Override
  public void ack(Object msgId) {}
  @Override
  public void fail(Object msgId) {}
}

下面是Bolt的代碼編寫:

public class SplitSentenceBolt extends BaseRichBolt {
  OutputCollector collector;

  @Override
  public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
    this.collector = collector;
  }
  @Override 消費者激活主要方法:分離成單個單詞
  public void execute(Tuple input) {
    for (String s : input.getString(0).split("\\s")) {
      collector.emit(new Values(s));
    }
  }
  @Override 定義新的字段名
  public void declareOutputFields(OutputFieldsDeclarer declarer) {
    declarer.declare(new Fields("word"));
  }

最後是裝配運行Spout和Bolt的客戶端調用代碼:

public class WordCountTopology {
  public static void main(String[] args) throws Exception {
    TopologyBuilder builder = new TopologyBuilder();
    builder.setSpout("tweet", new RandomSentenceSpout(), 2);
    builder.setBolt("split", new SplitSentenceBolt(), 4)
      .shuffleGrouping("tweet")
      .setNumTasks(8);
    builder.setBolt("count", new WordCountBolt(), 6)
      .fieldsGrouping("split", new Fields("word"));
    ..設置多個Bolt


    Config config = new Config();
    config.setNumWorkers(4);
    
    StormSubmitter.submitTopology("wordcount", config, builder.createTopology());

// Local testing
//LocalCluster cluster = new LocalCluster();
// cluster.submitTopology("wordcount", config, builder.createTopology());
//Thread.sleep(10000);
//cluster.shutdown();
}
}

在這個代碼中定義了一些參數比如Works的數目是4,其含義在後面詳細分析

下面我們要將上面這段代碼發佈部署到Storm中,首先了解Storm物理架構圖:

Nimbus是一個主後臺處理器,主要負責:
1.發佈分發代碼
2.分配任務
3.監控失敗。

Supervisor是負責當前這個節點的後臺工作處理器的監聽。

Work類似Java的線程,採取JDK的Executor 。

下面開始將我們的代碼部署到這個網絡拓撲中:



將代碼Jar包上傳到Nimbus的inbox,包括所有的依賴包,然後提交。

Nimbus將保存在本地文件系統,然後開始配置網絡拓撲,分配開始拓撲。

見下圖:



Nimbus服務器將拓撲Jar 配置和結構下載到 Supervisor,負載平衡ZooKeeper分配某個特定的Supervisor服務器,而Supervisor開始基於配置分配Work,Work調用JDK的Executor啓動線程,開始任務處理。

下面是我們代碼對拓撲分配的參數示意圖:



Executor啓動的線程數目是12個,組件的實例是16個,那麼如何在實際服務器中分配呢?如下圖:


圖中RsSpout代表我們的代碼中RandomSentenceSpout;SplitSentenceBolt簡寫爲SSbolt;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章