hbase之InitMetaProcedure流程
阿新 • • 發佈:2018-12-20
hbase中相關命令列操作在服務端都是由相應的Procedure來執行完成的,並不是一個單獨的操作,而是由其狀態機中的一系列狀態按照流程來完成的。特別的,我這次本著有圖有真相的原則來為大家分析這一流程。
這次,我們主要分析hbase在HMaster的初始化方法finishActiveMasterInitialization中,初始化Meta資訊的InitMetaProcedure流程。以最新github分支上的hbase程式碼而言,對應下圖中的:
如圖所示,在構造了InitMetaProcedure物件之後,ProcedureExecutor將其提交,而後,在ProcedureExecutor.pushProcedure方法中呼叫scheduler.addBack方法(此時的scheduler為MasterProcedureScheduler)。由於InitMetaProcedure間接實現了TableProcedureInterface介面,如下圖所示:
因此,會將該procedure加入任務佇列tableRunQueue中。
像其他許多框架(例如netty)的原理一樣,這裡必然是有一些執行緒在不斷地輪詢,直接或間接的從任務佇列中獲取任務。在我們當前分析的流程中,ProcedureExecutor.WorkerThread充當了這個角色。
從後續原始碼中,我們很容易知道,接著依次呼叫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,從而完成呼叫。
首先是呼叫queueAssign,然後呼叫AssignmentManager.queueAssign,將TRSP加入到MasterProcedureScheduler的tableRunQueue之中,並將TRSP當前狀態置為REGION_STATE_TRANSITION_OPEN。而後,在ProcedureExecutor.WorkerThread的輪詢中繼續呼叫scheduler.poll,這裡獲得狀態為REGION_STATE_TRANSITION_OPEN的TRSP,也就是剛剛轉換過來的TRSP(至於具體的流程,我們在下一節中具體分析)。接下來,我們繼續經過相同的流程,來到TransitRegionStateProcedure.executeFromState,由於當前狀態為REGION_STATE_TRANSITION_OPEN,故而呼叫openRegion方法。
在openRegion方法內呼叫了AssignmentManager.regionOpening,更新了regionNode為OPENING,而後呼叫了addChildProcedure(new OpenRegionProcedure(getRegion(), loc)),並且將當前狀態設定為REGION_STATE_TRANSITION_CONFIRM_OPENED。
由於上面addChildProcedure方法的呼叫,因此在該TRSP的subProcList中多了一個OpenRegionProcedure型別的Procedure。緊接著返回到Procedure.execProcedure。
由於其subprocs不為空,因此呼叫submitChildrenProcedures將OpenRegionProcedure加入到scheduler的呼叫佇列中。OpenRegionProcedure的父類為RegionRemoteProcedureBase,因此,在接下來在Procedure.doExecute的呼叫中,會轉到RegionRemoteProcedureBase.execute。
特別的,在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流程的完整呼叫。
如果大家感覺不錯,希望點一下下面的推薦。你的肯定是小編最大的動力。如果有疑問,也可以傳送郵件至[email protected],期待你的來信。