【Storm篇】--Storm中的同步服務DRPC

LHBlog發表於2018-01-25

一、前述

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.、我們可以修改並行度,使叢集的平行計算能力達到最優,主要實現平行計算。

 

 

 

相關文章