紧接着上一节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的深入应用以及源码剖析。请大家持续关注。
- java webservice生成客户端代码并调用
wsimport简介 在JDK的bin文件夹中,有一个wsimport.exe工具,可依据wsdl文件生成相应的类文件,将生存在本地这些类文件拷贝到需要使用的项目中,就可以像调用本地的类一样调用web ...
- rds
数据库:提供数据的高可用保证,至少要用双节点(一主已备,经典高可用架构:采用基于binlog的数据复制技术维护数据库的可用性和数据一致性.同时,高可用版的性能也可以满足业务生产环境的需求,配置上采用物 ...
- python3 第二十五章 - comprehensions(推导式)
推导式(又称解析式),是Python的一种独有特性.推导式是可以从一个数据序列构建另一个新的数据序列的结构体. 共有三种推导,在Python2和3中都有支持: 列表(list)推导式 字典(dict) ...
- dubbo入门学习 二 RPC框架
rpc框架解释 谁能用通俗的语言解释一下什么是 RPC 框架? - 远程过程调用协议RPC(Remote Procedure Call Protocol) 首先了解什么叫RPC,为什么要RPC,RPC ...
- canvas画布如何画图案例
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- RISC精简指令集系统计算机
特点: 选用使用频率高的简单指令,复杂指令由简单指令组合完成 固定指令长度 只有Load/Store指令访存,其他指令都在寄存器中进行 CPU中寄存器数量多 一定采用指令流水,大部分指令在一个时钟周期 ...
- ionic3 百度地图插件定位 问题
每次用 cordova-pluin-baidumaploaction 每调用一次 他只会执行一次 我想循环 但是每次都会初始化 把插件的java代码98行注释就好了
- 【洛谷P3369】【模板】普通平衡树题解
[洛谷P3369][模板]普通平衡树题解 题目链接 题意: 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3 ...
- 理解jsonp劫持漏洞
JSONP劫持 存在漏洞的链接格式类似于以下这种: http://www.xxx.com/xxx.do?callback=info 参数名也常见有cb jsoncb call jsoncall cba ...
- Python ImportError: No module named 'requests'的解决方法
import requests报错 Python ImportError: No module named 'requests'可能是requests没有安装 安装流程 1.cmd 2.cd D:\p ...