hbase服务端源码分析

—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();

就可以进行 拿到客户端的帐号了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值