[原]如何利用hadoop RPC框架實現和NameNode的交互

博客原文:hackershellnode

這篇文章主要介紹如何在已有的Hadoop RPC框架上,自定義新的方法實現和NameNode的交互。linux

在此以前,咱們須要準備:shell

  • hadoop的源碼
  • protobuf 2.5版本
  • JDK

hadoop 2.x版本中採用了Protocol Buffer (簡稱protobuf)做爲序列化和反序列化的工具,因此咱們在修改源碼時須要按照相應規則編寫message來實現數據的傳輸。框架

什麼是protobuf?

protobuf是Google 公司內部的混合語言數據標準,它很適合作數據存儲或 RPC 數據交換格式。是一種可用於通信協議、數據存儲等領域,而且和語言無關、平臺無關、可擴展的序列化結構數據格式。 簡單說來 Protobuf 的主要優勢就是:簡單,快。ide

安裝protobuf和編譯hadoop的過程網上的資料不少,我就直接跳過了,咱們能夠經過Idea導入hadoop的Maven項目,方便對源碼的修改工具

1. 修改proto文件,定義message和service

假設咱們如今要實現的是一個檢查某個文件或文件夾權限是否符合755,並對客戶端返回boolean值。 這是一個屬於Client和NameNode交互的一個方法,因此咱們在Idea中ctrl+shift+N快速的找到ClientNamenodeProtocol.proto,添加對應的message(結構化數據被稱爲message)oop

message CheckPermissionRequestProto {
    required string src = 1;
}
message CheckPermissionResponseProto {
    required bool checkPerm = 1;
}

咱們在這個文件中會看到除了string、bool類型的前面會有三種消息成員的規則,他們的含義分別是:ui

  • required:這個域在消息中必須恰好有1個
  • optional:這個域在消息中能夠有0或1個
  • repeated:這個域在消息中能夠有從多個,包括0個

在文件中找到service,並添加方法checkPermission方法this

service ClientNamenodeProtocol { 
 ...... 
rpc checkPermission(CheckPermissionRequestProto) returns(CheckPermissionResponseProto);
}

接下來編譯,編譯以後你能夠在ClientNamenodeProtocolProtos類(編譯後生成)的接口ClientNamenodeProtocol,看到新增長的方法了。code

2. ClientNamenodeProtocolPB文件

這個接口是client用來和NameNode進行交互的,它繼承了ClientNamenodeProtocol接口,即新生成的接口也在其中,這裏不用作修改

3. ClientNamenodeProtocolTranslatorPB類

這個類是將對ClientProtocol中方法的調用轉化爲RPC調用Namenode的服務,並將調用參數轉化爲PB的類型。 因此,咱們須要在ClientProtocol增長checkPermission方法,並在這個類中進行Override

在ClientProtocol中增長

@Idempotent
  public boolean checkPermission(String src)
       throws AccessControlException, FileNotFoundException,
       UnresolvedPathException, IOException;

在ClientNamenodeProtocolTranslatorPB類中

@Override
  public boolean checkPermission(String src) throws AccessControlException,
            FileNotFoundException, UnresolvedPathException, IOException {
     CheckPermissionRequestProto req = CheckPermissionRequestProto.newBuilder()
            .setSrc(src).build();
     try {
         return rpcProxy.checkPermission(null,req).getCheckPerm();
     } catch (ServiceException e) {
         throw ProtobufHelper.getRemoteException(e);
     }
  }

注意:要把CheckPermissionRequestProto進行import,不然編譯你懂的。

相應的咱們也須要在NameNodeRpcServer類中Override該方法,由於NamenodeProtocols繼承了ClientProtocol,這類負責處理全部到達NN的RPC call,他負責將請求轉化爲NN的方法的調用,所以也能夠看出它們的實現分層是很清晰的。

@Override // ClientProtocol
  public boolean checkPermission(String src)
      throws AccessControlException, FileNotFoundException, UnresolvedPathException, IOException {
      return namesystem.checkPermission(src);
  }

4. ClientNamenodeProtocolServerSideTranslatorPB類

該類是server端用來將ClientNamenodeProtocolTranslatorPB生成的PB格式的數據轉化爲本地調用的數據類型,因此增長改方法

@Override
  public CheckPermissionResponseProto checkPermission(RpcController controller,
                                                      CheckPermissionRequestProto req)
           throws ServiceException {
      try {
          boolean result = server.checkPermission(req.getSrc());
          return CheckPermissionResponseProto.newBuilder().setCheckPerm(result).build(); //將結果返回
      } catch (IOException e) {
          throw new ServiceException(e);
      }

  }

這裏的server就是NameNodeRpcServer,至關於調用NameNodeRpcServer的checkPermission方法,並在NameNodeRpcServer中調用FSNamesystem完成最後的邏輯

Namesystem類增長方法

boolean checkPermission(String src) throws IOException {  
      readLock();
      try {
          HdfsFileStatus fileStatus = getFileInfo(src,false); //這個方法我有作過修改,大家可能不同
          FsPermission fsPermission = new FsPermission((short)0755);
          if(fileStatus != null && fsPermission.equals(fileStatus.getPermission())) {
              return true;
          }
      } finally {
          readUnlock();
      }
      return false;
  }

接下來我就舉個例子怎麼調用,這只是部分代碼,詳細的本身看看源碼吧。

proxyInfo = NameNodeProxies.createProxy(conf, nameNodeUri,
      ClientProtocol.class, nnFallbackToSimpleAuth);
  this.namenode = proxyInfo.getProxy();
  namenode.checkPermission(src);

5. 最後一步就是編譯了

但願經過這個例子可以加深對hadoop實現的理解


參考資料

相關文章
相關標籤/搜索