0
点赞
收藏
分享

微信扫一扫

HBase HMaster启动和停止


HMaster(0.90.3) Startup:




main方法: 



new HMasterCommandLine(HMaster.class).doMain(args); //args为start


HMasterCommandLine: 用于启动/停止HMaster.



doMain: 运行Tool类的run方法. 继承关系:HMasterCommandLine-->ServerCommandLine-->Tool





HMasterCommandLine.run:



1. 构造CommandLine, 基本参数有三个: minServers, backup和(start/stop)



    * minServers: 集群拥有的最少regionserver数



    * backup: 是否是backup master



    * start/stop: 启动或者停止实例



2. 如果minServers存在



    设置hbase.regions.server.count.min为minServers的指, 默认为0



3. 如果backup存在



    如果有backup参数,设置hbase.master.backup为true, 默认为false



4. 如果是start



    startMaster()



5. 如果是stop



    stopMaster()



    



startMaster:



hbase.cluster.distributed=false: 



    切换至LocalHBaseCluster(1), 启动两个JVM, 一个ZK,一个master(1)+regionserver(1).



hbase.cluster.distributed=true: 



    1. 创建一个HMaster实例, new HMaster(Configuration).



        * 获取master的地址: ip:port, 默认port为60000, 通过hbase.master.port设置



        * 获取RPC的最大handler数, 通过hbase.regionserver.handler.count设置, 默认为10.



        * 创建HMaster RPCServer实例.



        * 设置master的replication



        * 启动rpc server的服务线程, 但是当前服务还处于不可用状态



        * 修改master的mapred.task.id.(为了更好的debug log, 查看HBase MR Job运行状态)



        * 连接zookeeper, 创建相关zk node(root-region-server, unassigned, rs, table)



        * 创建master的统计类MasterMetrics



    2. HMaster.start()



        * 创建activeMasterManager对象



        * 如果hbase.master.backup设置为true, sleep直到有其他master节点创建masterZNode节点.



            Backup会一直sleep直到有其他master上线.



        * blockUntilBecomingActiveMaster: 竞争master,如果失败则阻塞直到自己成为master



            > 首先尝试创建master节点(临时节点),如果成功,自己成为master,如果失败,说明已经存在master,不管成功失败,都会在master节点上添加一个watcher.



            > 如果失败, 获取当前master的节点data, 转换为HServerAddress, 如果发现地址就是自己, 说明自己做为master刚刚重启了,删除master节点.如果不是自己, 什么也不干.



            > 同步clusterHasActiveMaster, 如果clusterHasActiveMaster.get(),则wait on clusterHasActiveMaster, 等待被notify. notify以后递归调用blockUntilBecomingActiveMaster.



                notify由handleMasterNodeChange方法触发, 一但master的zk节点有create或者delete变化,就会触发。触发后同步clusterHasActiveMaster,并notifyAll所有wait着的backup master线程.



                这里有一个有意思的地方, 如果是master自己重启, 重启以后发现zk上的master节点是自己, 然后删除节点, 这个时候会有两种情况:



                1. 删除以后,先收到watcher event, 然后同步clusterHasActiveMaster, 将clusterHasActiveMaster设置为false,notifyAll. 然后blockUntilBecomingActiveMaster进入clusterHasActiveMaster同步模块,发现clusterHasActiveMaster.get()为false, 跳过wait环节,开始递归去竞争master节点.



                2. 删除以后, 代码block部分先获得了clusterHasActiveMaster锁, 发现clusterHasActiveMaster.get()为true,则wait,释放锁, 然后收到watcher event,设置clusterHasActiveMaster为false, 在notifyAll唤醒wait.



                有意思的地方就是网络的延迟可以造成不同的执行流程, 虽然结果都一样,但是网络快的情况下,可以少一次线程切换.



                这个地方还发现有一个小bug, 就是blockUntilBecomingActiveMaster方法的返回值cleanSetOfActiveMaster, 如果是第一次进入blockUntilBecomingActiveMaster,成功成为master, 返回值为true,如果是经过一次递归以后成为master, 返回值为false. 究其原因, 是因为代码没有将递归的返回值重置给调用者. 唉..主要是这个返回值没有发挥作用,所以也没人在意吧.



                // Try to become active master again now that there is no active master



                blockUntilBecomingActiveMaster();  =递归改为=> cleanSetOfActiveMaster = blockUntilBecomingActiveMaster();



        * finishInitialization: 顾名思义就是成为master以后需要完成一些初始化工作:



            1. 创建一些master工作需要的组件:



                > MasterFileSystem: 封装了master常用的一些文件系统操作,包括split log file, 删除region目录,删除table目录,删除cf目录等,检查文件系统状态等.



                > HConnection: 创建与zk的连接.



                > ExecutorService: 维护一个ExecutorMap, 一种Event对应一个Executor(线程池). 可以提交EventHandler来执行异步事件



                > ServerManager: 管理region server信息, 维护着online region server map, 同时也维护着每个region server rpc stub.



                > CatalogTracker: 同步-ROOT-和.META.的Server地址信息.



                > AssignmentManager: 负责管理和分配region, 同时它也会接受zk上关于region的event,根据event来完成region的上下线,关闭打开等工作.



                > LoadBalancer: 负责region在region server之间的移动, 关于balancer的策略, 可以通过hbase.regions.slop来设置load区间, 下次另启一篇来深入说明下.



                > RegionServerTracker: 通过ZK的Event来跟踪online region servers, 如果有rs下线, 删除ServerManager中对应的online regions.



                > ClusterStatusTracker: 维护集群状态, 通过shutdown节点来设置集群的up或者shutdown状态.



            2. 启动集群,启动所有的服务线程: 



                > 添加shutdown节点,并设置data为master name, 表示集群启动



                > 启动ExecutorService中各个Event的Executor.



                > 启动LogCleaner: 每个60秒启动一次清除old hlogs.



                > 启动WebApp Jetty Server: 用于通过web来访问master的状态(http://host:60010/).



                > 启动RPC Server, RPC开始接受Client请求.



            3. 等待region server来签到, 看策略, 这个过程应该不会太长, 如果网络抖动很厉害, 最多集群以最少regionserver数开始服务.



                > 等待region server来签到, 每次等待1.5s, 最少等待时间4.5s, 如果online region servers到达minCount,并且在一次等待时间内没有新的server签到, 则不再等待.



                > 统计当前online region servers总共持有的region数.



            4. Split log, 分发log, 执行数据恢复



                > 获取.logs目录的log目录列表, 根据目录名和online region server的名字进行对应.



                > 如果有regionserver存在待恢复log目录, 则开始split log工作



                > Split log/recovery的流程这个可以另起一篇来讲.



            5. 分配root和meta region



                > assignRootAndMeta: 检查Root region和first meta region是否被分配了, 如果没有, 分配他们.



            6. 根据集群是启动还是故障恢复的情况来做清理工作



                > 如果当前region数为0, 表示集群是startup, 清除所有unassignment region znode, 然后扫描meta表, 重新分配所有的region.



                > 如果当前region数大于0, 表示集群是failover状态, 将处于assignment状态的节点重新assign.



            7. 启动balancer定时执行线程.



            8. 启动.META.定时扫描清理线程.



        * loop: 循环等待, 直到Stop.



stopMaster:



    Stop以后, HMaster线程结束, finally进行清理工作:


stopChores(); //停止定时线程(balancer,meta清理,logCleaner) 
 
 
 

         // Wait for all the remaining region servers to report in IFF we were 
 
 
 

         // running a cluster shutdown AND we were NOT aborting. 
 
 
 

         if (!this.abort && this.serverManager != null && 
 
 
 

             this.serverManager.isClusterShutdown()) { 
 
 
 

           this.serverManager.letRegionServersShutdown(); 
 
 
 

         } 
 
 
 

         stopServiceThreads(); 
 
 
 

         // Stop services started for both backup and active masters 
 
 
 

         if (this.activeMasterManager != null) this.activeMasterManager.stop(); 
 
 
 

         if (this.catalogTracker != null) this.catalogTracker.stop(); 
 
 
 

         if (this.serverManager != null) this.serverManager.stop(); 
 
 
 

         if (this.assignmentManager != null) this.assignmentManager.stop(); 
 
 
 

         HConnectionManager.deleteConnection(this.conf, true); 
 
 
 

         this.zooKeeper.close();

举报

相关推荐

0 条评论