博客原文: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实现的理解
参考资料