Hadoop3.2.1 【 HDFS 】源碼分析 : RPC原理 [六] ProtobufRpcEngine 使用

ProtobufRpcEngine 目前是作爲Hadoop RPC 引擎唯一的實現方式.

WritableRpcEngine 在3.2.1版本已經標識爲廢棄,但依舊是默認實現的RPC引擎.

接下來,我們說一下如何使用, 過程比WritableRpcEngine 的使用要麻煩很多.

主要是在接口的定義和實現的寫法上有區別.

 

1. 定義協議

1.1.定義proto協議

根據Protocol的語法, 定義一個服務MetaInfo, 通過該服務的getMetaInfo接口,可以獲取到元數據的信息.

/**
 * 生成java代碼指令
 * protoc --java_out=. CustomProtocol.proto
 *
 */

option java_package = "org.apache.hadoop.rpc.protobuf";
option java_outer_classname = "CustomProtos";
option java_generic_services = true;
option java_generate_equals_and_hash = true;

package hadoop.common;

service MetaInfo {
  rpc getMetaInfo(GetMetaInfoRequestProto) returns (GetMetaInfoResponseProto);
}

message GetMetaInfoRequestProto {
  required string path = 1;
}

message GetMetaInfoResponseProto {
  required string info = 1;
}

 

 

1.2.根據定義好的proto協議生成java類,導入項目.

將定義好的協議保存成文件,命名爲CustomProtocol.proto. 在該文件的目錄下,執行命令

 

MacBook-Pro:proto sysadmin$ ls -l
total 8
-rw-r--r--@ 1 sysadmin  staff  526  4 20 09:56 CustomProtocol.proto
MacBook-Pro:proto sysadmin$
MacBook-Pro:proto sysadmin$
MacBook-Pro:proto sysadmin$ protoc --java_out=. CustomProtocol.proto
MacBook-Pro:proto sysadmin$
MacBook-Pro:proto sysadmin$
MacBook-Pro:proto sysadmin$ ls -l
total 8
-rw-r--r--@ 1 sysadmin  staff  526  4 20 09:56 CustomProtocol.proto
drwxr-xr-x  3 sysadmin  staff   96  4 20 11:53 org
MacBook-Pro:proto sysadmin$
MacBook-Pro:proto sysadmin$
MacBook-Pro:proto sysadmin$
MacBook-Pro:proto sysadmin$ cd org/apache/hadoop/rpc/protobuf
MacBook-Pro:protobuf sysadmin$
MacBook-Pro:protobuf sysadmin$ ls -l
total 104
-rw-r--r--  1 sysadmin  staff  49880  4 20 11:53 CustomProtos.java
MacBook-Pro:protobuf sysadmin$
MacBook-Pro:protobuf sysadmin$

 

這是在該目錄下, 會有一個文件目錄生成, 層級爲我們定義好的org.apache.hadoop.rpc.protobuf 路徑.

將裏面生成的java文件CustomProtos.java導入到項目中, 存放路徑與定義好的路徑一樣.

 

 

2.根據定義好的proto協議定義接口

 

創建一個接口,集成生成JAVA類中的CustomProtos.MetaInfo.BlockingInterface接口.

    // 接口信息 供server 和client 端使用
    @ProtocolInfo(
            protocolName = "org.apache.hadoop.rpc.CustomProtos$MetaInfoProtocol",
            protocolVersion = 1)
    public interface MetaInfoProtocol
            extends CustomProtos.MetaInfo.BlockingInterface {
    }

 

 

3.實現接口協議

創建一個類,實現剛剛定義好的MetaInfoProtocol 接口, 並且實現裏面的方法. 這個需要自己去寫代碼邏輯.

注意返回值和返回對象的寫法不太一樣.

 // 實現類
    public static class MetaInfoServer implements MetaInfoProtocol {

        @Override
        public CustomProtos.GetMetaInfoResponseProto getMetaInfo(RpcController controller,
                CustomProtos.GetMetaInfoRequestProto request) throws
                ServiceException {

            //獲取請求參數
            final String path = request.getPath();

            return CustomProtos.GetMetaInfoResponseProto.newBuilder().setInfo(path + ":3 - {BLOCK_1,BLOCK_2,BLOCK_3....").build();
        }
    }

 

4.創建Server服務, 並註冊協議.啓動RPC服務.

 

     public static void main(String[] args) throws  Exception{


        //1. 構建配置對象
        Configuration conf = new Configuration();

        //2. 協議對象的實例
        MetaInfoServer serverImpl =  new MetaInfoServer();
        BlockingService blockingService =
                CustomProtos.MetaInfo.newReflectiveBlockingService(serverImpl);

        //3. 設置協議的RpcEngine爲ProtobufRpcEngine .
        RPC.setProtocolEngine(conf, MetaInfoProtocol.class,
                ProtobufRpcEngine.class);
        
        //4. 構建RPC框架
        RPC.Builder builder = new RPC.Builder(conf);
        //5. 綁定地址
        builder.setBindAddress("localhost");
        //6. 綁定端口
        builder.setPort(7777);
        //7. 綁定協議
        builder.setProtocol(MetaInfoProtocol.class);
        //8. 調用協議實現類
        builder.setInstance(blockingService);
        //9. 創建服務
        RPC.Server server = builder.build();
        //10. 啓動服務
        server.start();
        
    }

 

 

5.創建Client服務,請求數據接口

 

    public static void main(String[] args) throws Exception {

        //1. 構建配置對象
        Configuration conf = new Configuration();

        //2. 設置協議的RpcEngine爲ProtobufRpcEngine .
        RPC.setProtocolEngine(conf, Server.MetaInfoProtocol.class,
                ProtobufRpcEngine.class);


        //3. 拿到RPC協議
        Server.MetaInfoProtocol proxy = RPC.getProxy(Server.MetaInfoProtocol.class, 1L,
                new InetSocketAddress("localhost", 7777), conf);

        //4. 發送請求
        CustomProtos.GetMetaInfoRequestProto obj =  CustomProtos.GetMetaInfoRequestProto.newBuilder().setPath("/meta").build();

        CustomProtos.GetMetaInfoResponseProto metaData = proxy.getMetaInfo(null, obj);

        //5. 打印元數據
        System.out.println(metaData.getInfo());

    }

 

 

6.測試結果

 

 

 

 

 

 

 

 

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