博客原文:hackershellnode
這篇文章主要介紹如何在已有的Hadoop RPC框架上,自定義新的方法實現和NameNode的交互。linux
在此以前,咱們須要準備:shell
hadoop 2.x版本中採用了Protocol Buffer (簡稱protobuf)做爲序列化和反序列化的工具,因此咱們在修改源碼時須要按照相應規則編寫message來實現數據的傳輸。框架
protobuf是Google 公司內部的混合語言數據標準,它很適合作數據存儲或 RPC 數據交換格式。是一種可用於通信協議、數據存儲等領域,而且和語言無關、平臺無關、可擴展的序列化結構數據格式。 簡單說來 Protobuf 的主要優勢就是:簡單,快。ide
安裝protobuf和編譯hadoop的過程網上的資料不少,我就直接跳過了,咱們能夠經過Idea導入hadoop的Maven項目,方便對源碼的修改工具
假設咱們如今要實現的是一個檢查某個文件或文件夾權限是否符合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
在文件中找到service,並添加方法checkPermission方法this
service ClientNamenodeProtocol { ...... rpc checkPermission(CheckPermissionRequestProto) returns(CheckPermissionResponseProto); }
接下來編譯,編譯以後你能夠在ClientNamenodeProtocolProtos類(編譯後生成)的接口ClientNamenodeProtocol,看到新增長的方法了。code
這個接口是client用來和NameNode進行交互的,它繼承了ClientNamenodeProtocol接口,即新生成的接口也在其中,這裏不用作修改
這個類是將對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); }
該類是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);
但願經過這個例子可以加深對hadoop實現的理解
參考資料