storm學習-Storm DRPC實戰 【轉】

轉自:http://www.51studyit.com/html/notes/20140329/47.html


DRPC ,Distributed Remote Procedure Call      
RPC本身是個成熟和古老的概念, Storm裏面引入DRPC主要是利用storm的實時計算能力來並行化CPU intensive的計算

  

DRPC, 只是storm應用的一個場景, 並且storm提供相應的編程框架, 以方便程序員

  

提供DRPC server的實現, 並提供對DRPC場景經行封裝的Topology  
對於storm, Topology內部其實是沒有任何區別的, 主要就是實現和封裝Topology和DRPC Server之間交互的spout和bolt  
具體交互過程如下圖,

  

image 

  

 

  

LinearDRPCTopologyBuilder

  

Storm封裝了這樣一個Topology實現LinearDRPCTopologyBuilder的topology builder

  

會使用DRPCSpout從DRPC服務器接收函數調用流, 每個函數調用被DRPC服務器標記了一個唯一的id.       
這個topology然後計算結果, 在topology的最後一個叫做ReturnResults的bolt會連接到DRPC服務器, 並且把這個調用的結果發送給DRPC服務器(通過那個唯一的id標識).       
DRPC服務器用那個唯一id來跟等待的客戶端匹配上,喚醒這個客戶端並且把結果發送給它.

  
   
public static class ExclaimBolt implements IBasicBolt {
    public void prepare(Map conf, TopologyContext context) {
    }
 
    public void execute(Tuple tuple, BasicOutputCollector collector) {
        String input = tuple.getString(1);
        collector.emit(new Values(tuple.getValue(0), input + "!"));
    }
 
    public void cleanup() {
    }
 
    public void declareOutputFields(OutputFieldsDeclarer declarer) {
        declarer.declare(new Fields("id", "result"));
    }
 
}
 
public static void main(String[] args) throws Exception {
    LinearDRPCTopologyBuilder builder
        = new LinearDRPCTopologyBuilder("exclamation");
    builder.addBolt(new ExclaimBolt(), 3);
    // ...
}

使用LinearDRPCTopologyBuilder

首先, 使用builder創建topology的時候, topology name要等於function name(PRC call)     
其次, 這裏不需要指定spout, 因爲已經做了封裝, 會自動從DRPC server讀取數據     
再者, 所有bolt的輸出的第一個field必須是request-id, 最後一般bolt的輸出一定是(request-id, result)     
最後, builder會自動將結果發給DRPC server

 

A more complex example, ReachTopology

前面的例子, 無法說明爲什麼要使用storm來實現RPC, 那個操作直接在RPC server上就可以完成     
當只有對並行計算和數據量有一定要求時, 才能體現出價值...     
ReachTopology, 每個人發送的URL都會被所有follower收到, 所以要計算某URL的reach, 只需要如下幾步,    
找出所有發送該URL的tweeter, 取出他們的follower, 去重複, 計數

Let's look at a more complex example which really needs the parallelism a Storm cluster provides for computing the DRPC function.   
The example we'll look at is computing the reach of a URL on Twitter.

The reach of a URL is the number of unique people exposed to a URL on Twitter. To compute reach, you need to:

  1. Get all the people who tweeted the URL 
  2. Get all the followers of all those people 
  3. Unique the set of followers 
  4. Count the unique set of followers 
  
LinearDRPCTopologyBuilder builder = new LinearDRPCTopologyBuilder("reach");
builder.addBolt(new GetTweeters(), 3);
builder.addBolt(new GetFollowers(), 12)
        .shuffleGrouping();
builder.addBolt(new PartialUniquer(), 6)
        .fieldsGrouping(new Fields("id", "follower"));
builder.addBolt(new CountAggregator(), 2)
        .fieldsGrouping(new Fields("id"));

首先對於LinearDRPCTopologyBuilder中, 沒有各個spout和bolt的id, 可能因爲是線性的, 所以沒有必要顯式指明關係, 按加入順序就可以  
GetTweeters(), 輸入(rpc-id, url), 輸出(rpc-id, tweeter)  
GetFollowers(), 輸入(rpc-id, tweeter), 輸出(rpc-id, follower)

對於PartialUniquer仔細分析一下,   
首先是基於id和follower的grouping, fieldsGrouping(new Fields("id", "follower")), 因爲可能由多個RPC同時執行, 所以只需要保證同一個RPC的followers被髮到同一個task即可.  
接着繼承BaseBatchBolt, 可以在finishBatch中emit結果  
使用HashSet來存放follower, 保證不重複

  
    public static class PartialUniquer extends BaseBatchBolt {
        BatchOutputCollector _collector;
        Object _id;
        Set<String> _followers = new HashSet<String>();
        
        @Override
        public void prepare(Map conf, TopologyContext context, BatchOutputCollector collector, Object id) {
            _collector = collector;
            _id = id;
        }

        @Override
        public void execute(Tuple tuple) {
            _followers.add(tuple.getString(1));
        }
        
        @Override
        public void finishBatch() {
            _collector.emit(new Values(_id, _followers.size()));
        }

        @Override
        public void declareOutputFields(OutputFieldsDeclarer declarer) {
            declarer.declare(new Fields("id", "partial-count"));
        }
    }

 

Non-linear DRPC topologies

當前LinearDRPCTopologyBuilder只能handle線性的bolt workflow     

LinearDRPCTopologyBuilder only handles "linear" DRPC topologies, where the computation is expressed as a sequence of steps (like reach). It's not hard to imagine functions that would require a more complicated topology with branching and merging of the bolts. For now, to do this you'll need to drop down into using CoordinatedBolt directly. Be sure to talk about your use case for non-linear DRPC topologies on the mailing list to inform the construction of more general abstractions for DRPC topologies.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章