1. 程式人生 > >HBase——HMaster啟動之二(HMaster執行緒的呼叫)

HBase——HMaster啟動之二(HMaster執行緒的呼叫)

  緊接著上一節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,其實這裡只是初始化了   來到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流程》中有相關介紹,感興趣的大家可以去看一下。   接下來來到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的深入應用以及原始碼剖析。請大家持續關注。