您的位置:首页 > 其它

hbase服务端源码分析

2016-07-15 17:26 316 查看

—client –>hmaster 和 client —> regionserver的流程

(源码基于hbase-1.1.5版本)

服务端主要有两个进程,hmaster 和 HRegionServer(其实 hmaster继承于 HRegionServer,这两个进程中既提供了web界面,同时也提供了rpc服务的调用,

如web服务在hmaster中是 http://127.0.0.1:16010/master-status

在regionserver中的web界面是 http://127.0.0.1:16030/rs-status

是通过HRegionServer.putUpWebUI 进行拉起jetty的不同业务的web界面

同时这两个进程也提供rpc服务,

hmaster 和 regionserver 绑定到不同的端口进行rpc ,就是通过 RpcServer 类进行的,在RSRpcServices(MasterRpcServices 是hamster调用的,其实MasterRpcServices也继承于 RSRpcServices) 中进行调用

通过 RpcServer.Listener 的方法,拉起一个nio server线程,来监听客户端的连接。



bind(acceptChannel.socket(), bindAddress, backlogLength);


然后在 Listener 线程当中,接收数据请求。

每一个链接都拿一下线程Reader 对象进行处理,创建的线程reader数量是通过(hbase.ipc.server.read.threadpool.size)

参数进行定义的,所以如果想提高线程的处理并发数,可以调整这个参数。

然后每个链接都创建 org.apache.hadoop.hbase.ipc.RpcServer.Connection.Connection

对象到 readKey.attach(c); 中调用 readAndProcess()方法读取连接中的数据

第一次连接上来时,调用readPreamble()方法,读取头部的数据如 AuthMethod.SIMPLE 、version 等头部信息

校验通过后,读取数据到data对象中,调用process()方法进行数据的处理

在数据处理中,会根据刚才的头部中上传的auth信息,进行判断是否进行权限校验。通过 变量 useSasl 保存。

在head部分,就可以拿到上传的用户名称.

接着通过authorizeConnection()方法进行权限的校验,如果校验失败,就返回出错



authorize(UserGroupInformation user, ConnectionHeader connection, InetAddress addr)


方法当中,会根据是否配置了HADOOP_SECURITY_AUTHORIZATION 参数进行权限的验证

通过

Class  c = getServiceInterface(services, connection.getServiceName());


拿到来源模块的接口方法

this.authManager.authorize(user != null ? user : null, c, getConf(), addr);


在这里进行KerberosInfo 的验证

所以其实Kerberos 的校验,就是通过来源的ip+username进行判断的。

当校验完成后,就调用processRequest()方法进行业务数据的处理了,在RpcServer的创建时,

有传入一个services参数,其实就是下面的方法

protected List<BlockingServiceAndInterface> getServices() {
List<BlockingServiceAndInterface> bssi = new ArrayList<BlockingServiceAndInterface>(2);
bssi.add(new BlockingServiceAndInterface(
ClientService.newReflectiveBlockingService(this),
ClientService.BlockingInterface.class));
bssi.add(new BlockingServiceAndInterface(
AdminService.newReflectiveBlockingService(this),
AdminService.BlockingInterface.class));
return bssi;
}


这个方法,已经包含所有的业务调用了,通过客户端上传的serviceName,拿到对应的模块,然后反射调用对应的方法

再次调用 md = this.service.getDescriptorForType().findMethodByName(header.getMethodName());

就可以找到对应的具体method的调用。

创建call调用对象

Call call = new Call(id, this.service, md, header, param, cellScanner, this, responder,
totalRequestSize, traceInfo, RpcServer.getRemoteIp());


然后放在 用CallRunner包装一下提交在 scheduler 线程池当中,

在CallRunner里面的run方法会调用到 RpcServer.call

resultPair = this.rpcServer.call(call.service, call.md, call.param, call.cellScanner,
call.timestamp, this.status)


在里面隐含着一个比较重要的的对象

RpcServer.CurCall.set(call);

把外面的所有参数放在call的当前线程当中,但是由于这个CurCall是protected的,在具体的方法当中,拿不到。

在业务方法中,为了拿到ip和user的信息,就需要从这个对象中拿出新的信息,

放在PayloadCarryingRpcController 对象,传到下个方法中了

在方法里面

Message result = service.callBlockingMethod(md, controller, param);


调用到service的接口方法,其实就是调用到 RSRpcServices 这个类当中,可以看到这个类的继承关系

RSRpcServices implements HBaseRPCErrorHandler,
AdminService.BlockingInterface, ClientService.BlockingInterface, PriorityFunction;


无论是调用hmaster还是调用hregionserver的rpc服务,都是最后回调到这个类当中。

如调用到 RSRpcServices.scan 方法当中,通过如下代码

String requestUserName = ((PayloadCarryingRpcController)controller).getRequestUserName();


就可以进行 拿到客户端的帐号了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hbase