緊接着上一節HMaster的構建完成。接下來會調用HMaster調用master.start(),master.join()。
由HMaster的繼承關系,很明顯,他是Runnable的子類。也就是說,在調用其start方法時,run方法被調用。
下面,讓我們來到HMaster.run方法。這里的涉及到多線程編程。一方面HMaster所在線程調用了super.run方法。另一方面另外啟動了一個daemon線程用於調用startActiveMasterManager方法。很多同學在這里可能就迷惑了,到底該先分析哪個呢,我在剛開始看的時候也比較懵逼,后來多分析了幾次發現,殊途同歸,先分析哪個都無所謂。下面,我先從簡單的開始介紹。
讓我們來到super.run的調用。來到這里一看,內容很多,各位同學不需要慌,讓我們再進入preRegistrationInitialization一探究竟。
來到preRegistrationInitialization,各位同學可能有所迷惑,為什么比較關鍵的方法有三個,而我在這里之框選了一個呢。原因很簡單,在HMaster啟動期間,他還運行不到下面去。
接着,讓我們一探究竟。看了兩個block方法,各位同學可能以為是在這里阻塞的,然而並不是,真正的等待是在下圖框選的waitForMasterActive。
來到waitForMasterActive(由於在這里我們研究的是HMaster,因此,這里的方法應該是HMaster.waitForMasterActive)。這個方法雖然比較短,確實困擾了我很久的一個地方。下圖框選的地方獲得的默認值為false,而isStopped與isAborted的獲得的初始值都是false。因此,HMaster在啟動時,包括啟動后,都一直在這里輪詢等待。因為啟動后只是將activeMaster置位false。在tablesOnMaster默認值為false的情況下,並沒有任何作用。也就是說只有后面的兩個值發生變動后,這種等待才會被打破。分析到這里,各位同學應該可以安心的分析那個守護線程了。
讓我們來到HMaster.startActiveMasterManager方法中,首先通過調用activeMasterManager.blockUntilBecomingActiveMaster確定當前Master為ActiveMaster,然后再調用finishActiveMasterInitialization方法。這里我們只分析ActiveMaster的流程,並不介紹StandyMaster。在blockUntilBecomingActiveMaster方法中的調用並不是很難,感興趣的同學可以簡單。在activeMasterManager.blockUntilBecomingActiveMaster。這里我們把重點放在finishActiveMasterInitialization。
接下來讓我們來到finishActiveMasterInitialization方法。
這個方法是出奇的長,在這里,我們還是按照一張張的來介紹,以避免大家到后面會忘記前面的。
首先我們分析第一個方法initializeMemStoreChunkCreator,其實這里只是初始化了
首先我們分析第一個方法initializeMemStoreChunkCreator,其實這里只是初始化了
來到ChunkCreator的構造方法,我們可以看到其主要調用了initializePools方法
在initializePool方法中,主要構建了MemStoreChunkPool,並且將其加入heapMemoryManager的管理之中。而在構建MemStoreChunkPool的過程中,創建了Chunk,並將其放入reclaimedChunks中,初始化並開始周期調用統計線程StatisticsThread,將其內存數據打印出來。這里設計到HBase的內存管理,我將在后續的章節中專門拿出一講來為大家講解。這里就介紹到這。
接着來到MasterFileSystem的構造方法中,這里主要獲得了fs與walFs。
接下來,讓我們來到createServerManager方法中,在這里首先構建了clusterConnection對象,其中主要構建了ShortCircuitingClusterConnection與MetaTableLocator。這里簡單略過,詳細內容請看我的另外一篇博文《HBase之setupClusterConnection流程》。然后構造了ServerManager,他就是HMaster用於管理region servers信息的類。
再接下來,來到createProcedureExecutor,這是一個重量級的方法。
讓我們首先來到MasterProcedureEnv的構造方法,這個構造方法看似簡單,卻同時構造了兩個重要的對象。RSProcedureDispatcher、MasterProcedureScheduler。其中的RSProcedureDispatcher負責HMaster向RegionServer的Procedure調用,而MasterProcedureScheduler負責的是Master自身的Procedure的調用。
需要注意的是,在MasterProcedureScheduler中有幾個隊列的成員變量,他們的作用就是保存將要調用procedure,然后由具體線程調用。
接下來是WALProcedureStore,這里主要傳入了一個LeaseRecovery對象,而他的實際類型是MasterProcedureEnv.WALStoreLeaseRecovery,他的主要作用是對hdfs的文件恢復租約。
在ProcedureExecutor的構造方法中只是對其成員變量的賦值,並沒有什么比較重要的方法。不過,在這里我們需要記住,在這里傳入的store類型為WALProcedureStore,scheduler類型為MasterProcedureScheduler。
接下來來到WALProcedureStore.start方法。在這里,根據傳入的線程數初始化了Slot數量,並且啟動WALProcedureStoreSyncThread線程用於調用syncLoop方法。這里就簡單略過,我們先繼續后面的流程。
下面,來到ProcedureExecutor.init方法。這里將WorkerThread,添加到workerThread成員變量中。接着調用store.recoverLease,恢復相關文件的租約。然后調用scheduler.start,將scheduler中的running置位true。
這里簡單看一下WorkThread中的run方法。這里的流程在我的博文《hbase之InitMetaProcedure流程》中有相關介紹,感興趣的大家可以去看一下。
這里簡單看一下WorkThread中的run方法。這里的流程在我的博文《hbase之InitMetaProcedure流程》中有相關介紹,感興趣的大家可以去看一下。
接下來來到finishActiveMasterInitialization的第二張圖。
首先創建了AssignmentManager,AssignmentManager的作用就是用來操作assign/unassign。然后調用了AssignmentManager.start方法。關於AssignmentManager的相關調用我在博文《HBase之AssignmentManager相關調用》中有介紹,感興趣的同學可以去看一下。接下來構造並調用了RegionServerTracker,用於通過ZK跟蹤在線RegionServers。
然后調用了initializeZKBasedSystemTrackers方法,在這里初始化了所有基於ZK的系統跟蹤器。盡管如此,還是有些方法值得我們探究。首先介紹各種Tracker,這些都是直接或間接繼承自ZKListener,或者將傳入的ZK保存到自己的成員變量中用來實現對自己所在ZK目錄中狀態的監聽。
然后來到LoadBalancerFactory.getLoadBalancer方法,這里調用ReflectionUtils.newInstance通過反射創建了StochasticLoadBalancer,同時由於StochasticLoadBalancer實現了Configurable接口。因此在通過反射創建了StochasticLoadBalancer,緊接着變調用了setConf方法。在StochasticLoadBalancer.setConf中調用了構造了各種CostFunction。在這里我們簡單略過
。
。
接下來來到方法的后面,這里構建了SnapshotManager、MasterFlushTableProcedureManager(二者都繼承自抽象類ProcedureManagerHost)並且注冊到創建的MasterProcedureManagerHost對象中。接着調用了MasterProcedureManagerHost.initialize,調用了剛剛注冊進來的兩個對象initialize方法。
接下來來到finishActiveMasterInitialization的下一張圖。如果已經不是第一次調用,那么就不會調用框二中所選的內容,不過,感興趣的同學可以去看我的博客《hbase之InitMetaProcedure流程》。這里我們只介紹框一與框三中的內容。
來到HMaster.startServiceThreads。這里的executorService大家可能已經忘記了,他是在HMaster構造時實例化的(具體是在HMaster的父類HRegionServer構造的最后)。通過調用executorService.startExecutorService,ExecutorType的類型與最大線程數量傳入ExecutorService.startExecutorService,構造了相應名稱的線程池,並且將其置於ExecutorService的成員變量executorMap的管理之下。接下來我們簡單介紹一下getChoreService().scheduleChore。這是ScheduledChore調用的通用方式,通過getChoreService獲取初始化的成員變量choreService(同樣在HMaster的父類HRegionServer構造的最后實例化的),然后調用其scheduleChore方法,在上面我已經講過了,這里就不再贅述了。
接着調用waitForRegionServers等待RegionServer的注冊。關於HMaster與HRegionServer的交互流程我在以后的章節中會介紹到。接下來調用waitUntilMetaOnline,等待hbase:meta上線並且可讀。以為后面assignmentManager.joinCluster中loadMeta做准備。
接下來,我們首先來到assignmentManager.joinCluster
在loadMeta中,主要用於載入hbase:meta的各個Region,並且將其加入到regionStates的管理中。接下來調用processOfflineRegions,當前保存在AssignmentManager.regionStates中,其狀態OFFLINE的Regions。然后將成員變量ritChore加入到ProcedureExecutor的timeoutExecutor中。
接下來調用了TableStateManager.start,將當前的表都置於TableStateManager的管理之中。
下面框選中的內容雖然多,但是,我們只是簡單介紹。因為這里已經不是很主要的流程了。首先是幾個ScheduledChore的子類構建並調用。接着,調用ServerManager.startChore其主要講FlushedSequenceIdFlusher這個ScheduledChore構建並開始調用。然后,調用了initClusterSchemaService、cpHost.preMasterInitialization。最后,將三個ConfigurationObserver注冊到configurationManager中。
來到FAMI中的最后一張圖,這里我們只是引出,關於其中具體的流程,我們將在后面意義道來。在后面主要介紹initMobCleaner。
下圖首先構建了ExpiredMobFileCleanerChore(這個ScheduledChore用於定期刪除過期的mob文件),然后將其加入到choreService中並啟動。緊接着構建並啟動了MobCompactionChore,這個ScheduledChore用於定期壓縮以合並小的mob文件。然后構建了MasterMobCompactionThread。
至此,HMaster的啟動流程就完成了,感謝大家內心觀看。說實話,不僅各位看的辛苦,小編我寫的也很辛苦,所以,留下你的贊,小編更有動力發表更好的文章。
學完這一節,很多同學可能會對netty的原理想要有比較深入的了解。請各位同學不要着急,在介紹完HBase中比較重要的流程,小編就會為大家帶來netty的深入應用以及源碼剖析。請大家持續關注。
