一、前述
Drpc(分散式遠端過程呼叫)是一種同步服務實現的機制,在Storm中客戶端提交資料請求之後,立刻取得計算結果並返回給客戶端。同時充分利用Storm的計算能力實現高密度的並行實時計算。
二、具體原理
DRPC 是通過一個 DRPC 服務端(DRPC server)來實現分散式 RPC 功能的。
DRPC Server 負責接收 RPC 請求,並將該請求傳送到 Storm中執行的 Topology,等待接收 Topology 傳送的處理結果,並將該結果返回給傳送請求的客戶端。
(其實,從客戶端的角度來說,DPRC 與普通的 RPC 呼叫並沒有什麼區別。)
DRPC設計目的是為了充分利用Storm的計算能力實現高密度的並行實時計算。
(Storm接收若干個資料流輸入,資料在Topology當中執行完成,然後通過DRPC將結果進行輸出。)
流程圖如下:
解釋:
客戶端通過向 DRPC 伺服器傳送待執行函式的名稱以及該函式的引數來獲取處理結果。實現該函式的拓撲使用一個DRPCSpout 從 DRPC 伺服器中接收一個函式呼叫流。DRPC 伺服器會為每個函式呼叫都標記了一個唯一的 id。隨後拓撲會執行函式來計算結果,並在拓撲的最後使JoinResult的Bolt實現資料的聚合, ReturnResults 的 bolt 連線到 DRPC 伺服器,根據函式呼叫的 id 來將函式呼叫的結果返回。
三、實現方式
方法1.
通過LinearDRPCTopologyBuilder (該方法也過期,不建議使用)
該方法會自動為我們設定Spout、將結果返回給DRPC Server等,我們只需要將Topology實現
package com.sxt.storm.drpc; import backtype.storm.Config; import backtype.storm.LocalCluster; import backtype.storm.LocalDRPC; import backtype.storm.StormSubmitter; import backtype.storm.drpc.LinearDRPCTopologyBuilder; import backtype.storm.topology.BasicOutputCollector; import backtype.storm.topology.OutputFieldsDeclarer; import backtype.storm.topology.base.BaseBasicBolt; import backtype.storm.tuple.Fields; import backtype.storm.tuple.Tuple; import backtype.storm.tuple.Values; public class BasicDRPCTopology { public static class ExclaimBolt extends BaseBasicBolt { @Override public void execute(Tuple tuple, BasicOutputCollector collector) { String input = tuple.getString(1); collector.emit(new Values(tuple.getValue(0), input + "!")); } @Override public void declareOutputFields(OutputFieldsDeclarer declarer) { declarer.declare(new Fields("id", "result")); } } public static void main(String[] args) throws Exception { LinearDRPCTopologyBuilder builder = new LinearDRPCTopologyBuilder("exclamation");//通過LinearDRPCTopologyBuilder 定義拓撲 //exclamation是函式名稱 builder.addBolt(new ExclaimBolt(), 3); Config conf = new Config(); if (args == null || args.length == 0) { LocalDRPC drpc = new LocalDRPC(); LocalCluster cluster = new LocalCluster(); cluster.submitTopology("drpc-demo", conf, builder.createLocalTopology(drpc));//這是拓撲名稱 for (String word : new String[] { "hello", "goodbye" }) { System.err.println("Result for \"" + word + "\": " + drpc.execute("exclamation", word)); } cluster.shutdown(); drpc.shutdown(); } else { conf.setNumWorkers(3); StormSubmitter.submitTopologyWithProgressBar(args[0], conf, builder.createRemoteTopology()); } } }
方法2:
直接通過普通的拓撲構造方法TopologyBuilder來建立DRPC拓撲
需要手動設定好開始的DRPCSpout以及結束的ReturnResults
package com.sxt.storm.drpc; import backtype.storm.Config; import backtype.storm.LocalCluster; import backtype.storm.LocalDRPC; import backtype.storm.drpc.DRPCSpout; import backtype.storm.drpc.ReturnResults; import backtype.storm.topology.BasicOutputCollector; import backtype.storm.topology.OutputFieldsDeclarer; import backtype.storm.topology.TopologyBuilder; import backtype.storm.topology.base.BaseBasicBolt; import backtype.storm.tuple.Fields; import backtype.storm.tuple.Tuple; import backtype.storm.tuple.Values; public class ManualDRPC { public static class ExclamationBolt extends BaseBasicBolt { @Override public void declareOutputFields(OutputFieldsDeclarer declarer) { declarer.declare(new Fields("result", "return-info")); } @Override public void execute(Tuple tuple, BasicOutputCollector collector) { String arg = tuple.getString(0); Object retInfo = tuple.getValue(1); collector.emit(new Values(arg + "!!!", retInfo)); } } public static void main(String[] args) { TopologyBuilder builder = new TopologyBuilder(); LocalDRPC drpc = new LocalDRPC(); DRPCSpout spout = new DRPCSpout("exclamation", drpc);//自定義drpc spout builder.setSpout("drpc", spout); builder.setBolt("exclaim", new ExclamationBolt(), 3).shuffleGrouping("drpc"); builder.setBolt("return", new ReturnResults(), 3).shuffleGrouping("exclaim");//自定義結束的ReturnResults
LocalCluster cluster = new LocalCluster(); Config conf = new Config(); cluster.submitTopology("exclaim", conf, builder.createTopology()); System.err.println(drpc.execute("exclamation", "aaa")); System.err.println(drpc.execute("exclamation", "bbb")); } }
四、Storm執行模式
1、本地模式
public static void main(String[] args) { TopologyBuilder builder = new TopologyBuilder(); LocalDRPC drpc = new LocalDRPC(); DRPCSpout spout = new DRPCSpout("exclamation", drpc); builder.setSpout("drpc", spout); builder.setBolt("exclaim", new ExclamationBolt(), 3).shuffleGrouping("drpc"); builder.setBolt("return", new ReturnResults(), 3).shuffleGrouping("exclaim"); LocalCluster cluster = new LocalCluster(); Config conf = new Config(); cluster.submitTopology("exclaim", conf, builder.createTopology()); System.err.println(drpc.execute("exclamation", "aaa")); System.err.println(drpc.execute("exclamation", "bbb")); }
2.遠端模式(叢集模式)
修改配置檔案conf/storm.yaml
drpc.servers:
- "node1“
啟動DRPC Server
bin/storm drpc &
通過StormSubmitter.submitTopology提交拓撲
public static void main(String[] args) { DRPCClient client = new DRPCClient("node1", 3772);//通訊埠 try { String result = client.execute("exclamation", "11,22"); System.out.println(result); } catch (TException e) { e.printStackTrace(); } catch (DRPCExecutionException e) { e.printStackTrace(); }
總結:Drpc分散式遠端呼叫幫我們
1、 實現了drpcSpout用來向後傳送資料,我們只需要傳參即可。
2、 實現了最後的JoinResult用來匯合結果,ReturnResult用來將結果返回客戶端。從而達到實時的目的。
3.、我們可以修改並行度,使叢集的平行計算能力達到最優,主要實現平行計算。