hbase中相关命令行操作在服务端都是由相应的Procedure来执行完成的,并不是一个单独的操作,而是由其状态机中的一系列状态按照流程来完成的。特别的,我这次本着有图有真相的原则来为大家分析这一流程。
这次,我们主要分析hbase在HMaster的初始化方法finishActiveMasterInitialization中,初始化Meta信息的InitMetaProcedure流程。以最新github分支上的hbase代码而言,对应下图中的:

如图所示,在构造了InitMetaProcedure对象之后,ProcedureExecutor将其提交,而后,在ProcedureExecutor.pushProcedure方法中调用scheduler.addBack方法(此时的scheduler为MasterProcedureScheduler)。由于InitMetaProcedure间接实现了TableProcedureInterface接口,如下图所示:

因此,会将该procedure加入任务队列tableRunQueue中。


从后续源码中,我们很容易知道,接着依次调用ProcedureExecutor.executeProcedure,procedure.doExecute。特别的,在procedure.doExecute方法中,首先通过其抽象父类Procedure.doExecute,然后调用其抽象父类StateMachineProcedure.execute,最后调用InitMetaProcedure.executeFromState。由于InitMetaProcedure.getInitialState中获得的InitMetaProcedure的初始状态为InitMetaState.INIT_META_ASSIGN_META,因此会调用下面的addChildProcedure方法。

特别的,方法内首先调用AssignmentManager.createAssignProcedures,AssignmentManager.createAssignProcedure,TransitRegionStateProcedure.assign等方法,构建了一个TRSP Procedure。并且初始化TRSP为初始状态为RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE,
最终状态为RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_OPENED的 Procedure。

然后通过调用addChildProcedure方法将刚刚构建的TRSP添加到其subProcList中。接着,回到了StateMachineProcedure.execute方法中,将刚刚构建好的subProcList以数组形式返回,一直到ProcedureExecutor.execProcedure。接着调用ProcedureExecutor.initializeChildren设置subprocs的ParentProcId、RootProcId与ProcId实现对subprocs与父procedure的关联。然后,由于subprocs不为空,调用submitChildrenProcedures,将刚刚创建的TRSP继续加入到scheduler的任务队列中。

而后,在WorkerThread.run方法中继续轮询调用。接下来的流程与上面所述的大致相同,只是这次在执行Procedure.doExecute中调用到了TransitRegionStateProcedure.execute。而后才继续调用StateMachineProcedure.execute。接着就调用到了TransitRegionStateProcedure.executeFromState。根据下图所示,结合刚刚TRSP初始化时的状态,我们很容易便知道,TRSP将依次经过REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE-->REGION_STATE_TRANSITION_OPEN-->REGION_STATE_TRANSITION_CONFIRM_OPENED,从而完成调用。

在openRegion方法内调用了AssignmentManager.regionOpening,更新了regionNode为OPENING,而后调用了addChildProcedure(new OpenRegionProcedure(getRegion(), loc)),并且将当前状态设置为REGION_STATE_TRANSITION_CONFIRM_OPENED。

由于上面addChildProcedure方法的调用,因此在该TRSP的subProcList中多了一个OpenRegionProcedure类型的Procedure。紧接着返回到Procedure.execProcedure。

特别的,在execute的执行流程中,涉及到客户端与服务端的调用,我们将详细讲述。

如图所示,通过env.getRemoteDispatcher获取到RSProcedureDispatcher,调用其addOperationToNode方法。在addOperationToNode方法内调用node.add方法。

特别注意上图的node类型为RemoteProcedureDispatcher.BufferNode,其add方法如下图所示:

这里调用了timeoutExecutor.add方法,其中timeoutExecutor类型为TimeoutExecutorThread。这里我们只附一张图,详细流程将在下节叙述。

略过这里,回到RegionRemoteProcedureBase.execute,该方法最后调用了event.suspendIfNotReady,将该procedure加入了ProcedureEvent.suspendedProcedures,最后间接的加入到轮询队列中。至此,CreateTableProcedure与TRSP依次调用下图中标亮的方法,从而完成InitMetaProcedure流程的完整调用。

如果大家感觉不错,希望点一下下面的推荐。你的肯定是小编最大的动力。如果有疑问,也可以发送邮件至15935152719@163.com,期待你的来信。