標籤:style java 使用 io 資料 for art ar
官方提供的storm starter樣本中,有很多應用的例子,對storm的應用情境理解很有協助。本文結合源碼來進行功能分解,記錄一下,作為記憶索引吧。
先來看一個比較簡單的樣本:WordCountTopology,原版代碼該樣本是為了說明多語言適配而做的應用情境,主要功能是隨機產生一些String,將這些String劃分分組,統計各單詞出現數量。後來修改了一下,去掉了py調用的地方。使用java來進行片語劃分。
先來看一下Topology:
public static void main(String[] args) throws Exception {TopologyBuilder builder = new TopologyBuilder();builder.setSpout("spout", new RandomSentenceSpout(), 5); // 資料來源builder.setBolt("split", new SplitSentence(), 8).shuffleGrouping("spout"); // 單詞劃分builder.setBolt("count", new WordCount(), 12).fieldsGrouping("split",new Fields("word")); // 統計單詞出現個數Config conf = new Config();conf.setDebug(true);if (args != null && args.length > 0) { conf.setNumWorkers(3); StormSubmitter.submitTopologyWithProgressBar("wordCount", conf,builder.createTopology());} else { conf.setMaxTaskParallelism(3); LocalCluster cluster = new LocalCluster(); cluster.submitTopology("word-count", conf, builder.createTopology()); Thread.sleep(10000); cluster.shutdown();}}
RandomSentenceSpout功能很簡單,隨機產生字串到tuple中,key為word。
再看一下bolt,該樣本中使用了兩類分組方式shuffleGrouping(隨機分組),fieldsGrouping(按欄位分組)。使用shuffleGrouping來進行單詞劃分,為了保證單詞統計時都在一個bolt中進行,使用fieldsGrouping來進行word劃分統計,運行時會看到相同key值的tuple會分配到同一線程上。
public static class SplitSentence 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(" ")) { // 將Spout接收到的tuple按空格進行分解,產生單詞資料流collector.emit(new Values(word));}}public void cleanup() {}public void declareOutputFields(OutputFieldsDeclarer declarer) {declarer.declare(new Fields("word")); // 定義key值}@Overridepublic Map<String, Object> getComponentConfiguration() {return null;}} 單詞統計bolt:
public static class WordCount extends BaseBasicBolt {Map<String, Integer> counts = new HashMap<String, Integer>();@Overridepublic void execute(Tuple tuple, BasicOutputCollector collector) {String word = tuple.getString(0);Integer count = counts.get(word);if (count == null)count = 0;count++;counts.put(word, count);collector.emit(new Values(word, count)); // 輸出結果word + word number}@Overridepublic void declareOutputFields(OutputFieldsDeclarer declarer) {declarer.declare(new Fields("word", "count")); }}
總結:
通常情況下,為了保證資料可靠性與完整性,實現一個Bolt,可以實現IRichBolt介面或繼承BaseRichBolt,如果不想自己處理結果反饋,可以實現IBasicBolt介面或繼承BaseBasicBolt,相當於自動處理了prepare方法和collector.emit.ack(inputTuple);