get/delete/put/append/increment等等客户可用的函数都在客户端的HTable.java文件
HTable通过在connection调用getTable获得,其实是调用HTable的构造方法创建一个HTable对象
HTable有几个属性要注意:
this.pool = pool; 线程池
this.rpcCallerFactory = rpcCallerFactory;
this.rpcControllerFactory = rpcControllerFactory;
rpc的控制工厂类
multiAp = this.connection.getAsyncProcess(); 异步处理的进程
this.locator = new HRegionLocator(tableName, connection); region的定位类
客户端的put请求最后都是通过调用getBufferedMutator().mutate(put)
接下来的所有操作都是在BufferedMutatorImpl里面完成,在BufferedMutatorImpl有一个AsyncProcess属性ap
在操作中先对每个put的方法做预有效判断,有效判断后累加每个put的大小,并且缓存每个put到列表writeAsyncBuffer
在提交有做处理,当put的大小之和大于 hbase.client.write.buffer的值(默认为2M),调用backgroundFlushCommits(false)进行提交
当ap报错了,则强制提交backgroundFlushCommits(true)
在最后也会flush() 通过backgroundFlushCommits(true)进行强制提交
所有的提交都是通过ap.submit(tableName,writeAsyncBuffer,true,null,false) 完成
进入submit函数,可以看到它循环遍历参数writeAsyncBuffer中的每一行,通过connection.locateRegion函数找到其在集群的位置loc,将该位置与操作action一起绑定在变量actionByServer中。
这里的region定位是由ClusterConnection类型的变量connection完成的,进入其locateRegion方法可以看出,如果客户端有缓存,则直接从缓存读取,否则从META表中读出了region所处的位置,并缓存此次的读取结果。返回的结果是RegionLocations类型的变量。
actionByServer是一个Map<ServerName,MulteAction<Row>>类型的变量,从该变量的类型定义可以看出,其将用户的一批写请求中,写入regionserver地址相同的动作归类到一起。
注意:是所有针对同个server的所有操作都放在里面,不是单个操作
最后调用sumitMultiActions函数将所有请求提交给服务端,它接受了上面的actionByServer作为参数,内部实例化一个AsyncRequestFutureImpl类执行异步的提交动作
AsyncRequestFutureImpl.sendMultiAction()完成提交
在里面创建一个SingleServerRequestRunnable对象,这个是个Runnable对象
在SingleServerRequestRunnable的run方法中,创建MultiServerCallable对象,用于实际将用户请求与服务端建立联系,实际上
通过调用在SingleServerRequestRunnable的MultiServerCallable.callWithoutRetries()
在callWithoutRetries()里面prepare()进行rpcClient的通道创建,call()提交逻辑
getStub().multi()
.ClientProtos.ClientService.BlockingStub
BlockingRpcChannelImplementation.callBlockingMethod()
RpcClientImpl.callBlockingMethod()
接下来的操作是到服务端的操作,这里是流程图