本文共 11718 字,大约阅读时间需要 39 分钟。
版本:HBase 0.94.15-cdh4.7.0
说明:
这部分参考和使用了上的代码(注意:原仓库已经被作者删除了),包括该作者自己写的一些和。
首先,在IDE里启动HMaster和HRegionServer:
运行/hbase/src/test/java/my/test/start/HMasterStarter.java
,当看到提示Waiting for region servers count to settle
时, 再打开同目录中的HRegionServerStarter,统一运行该类。
此时会有两个Console,在HMasterStarter这个Console最后出现Master has completed initialization
,这样的信息时就表示它启动成功了,而HRegionServerStarter这个Console最后出现Done with post open deploy task
这样的信息时说明它启动成功了。
运行HMasterStarter类启动HMaster:
package my.test.start;import java.io.File;import my.test.TestBase;import org.apache.hadoop.hbase.HConstants;import org.apache.hadoop.hbase.master.HMaster;import org.apache.hadoop.hbase.zookeeper.MiniZooKeeperCluster;public class HMasterStarter { public static void deleteRecursive(File[] files) { if (files == null) return; for (File f : files) { if (f.isDirectory()) { deleteRecursive(f.listFiles()); } f.delete(); } } public static void main(String[] args) throws Exception { File f = TestBase.getTestDir(); //删除临时测试目录 deleteRecursive(f.listFiles()); new ZookeeperThread().start(); Thread.sleep(1000); HMaster.main(new String[] { "start" }); } public static class ZookeeperThread extends Thread { public void run() { MiniZooKeeperCluster zooKeeperCluster = new MiniZooKeeperCluster(); File zkDataPath = new File(TestBase.sharedConf.get(HConstants.ZOOKEEPER_DATA_DIR)); int zkClientPort = TestBase.sharedConf.getInt(HConstants.ZOOKEEPER_CLIENT_PORT, 2181); zooKeeperCluster.setDefaultClientPort(zkClientPort); try { zooKeeperCluster.startup(zkDataPath); } catch (Exception e) { e.printStackTrace(); } } }}
HMaster的入口是main方法,main方法需要传递一个参数,start或者stop。
main方法内首先打印hbase版本信息,然后在调用HMasterCommandLine的doMain方法。HMasterCommandLine继承自ServerCommandLine类并且ServerCommandLine类实现了Tool接口。
public void doMain(String args[]) throws Exception { int ret = ToolRunner.run( HBaseConfiguration.create(), this, args); if (ret != 0) { System.exit(ret); } }
doMain方法内会调用ToolRunner的run方法,查看ToolRunner类可以知道,实际上最后会调用HMasterCommandLine的run方法。
接下来会解析参数,根据参数值判断是执行startMaster方法还是stopMaster方法。
startMaster方法中分两种情况:本地模式和分布式模式。如果是分布式模式,通过反射调用HMaster的构造方法,并调用其start和join方法。
HMaster继承自HasThread类,而HasThread类实现了Runnable接口,故HMaster也是一个线程。
HMaster类继承关系如下图:
1、构造方法总体过程
创建Configuration并设置和获取一些参数。包括:
192.168.1.129,60000,1404117936154
master + "-" + this.serverName.toString()
Replication.decorateMasterConfiguration(this.conf);
mapred.task.id
,如果其为空,则其值为:"hb_m_" + this.serverName.toString()
涉及到的参数有:
hfile.block.cache.sizehbase.master.dns.interfacehbase.master.dns.nameserverhbase.master.porthbase.master.ipc.addresshbase.master.handler.counthbase.regionserver.handler.counthbase.master.buffer.for.rs.fatalshbase.zookeeper.client.keytab.filehbase.zookeeper.client.kerberos.principalhbase.master.keytab.filehbase.master.kerberos.principalhbase.master.logcleaner.pluginsmapred.task.idhbase.node.health.script.frequencyhbase.regionserver.separate.hlog.for.metahbase.master.wait.for.log.splitting
2、创建rpcServer并启动其中的线程:
这部分涉及到RPC的使用,包括的知识点有动态代理
、Java NIO
等。
通过反射创建RpcEngine的实现类,实现类可以在配置文件中配置(hbase.rpc.engine
),默认实现为WritableRpcEngine。 调用getServer方法,其实也就是new一个HBaseServer类。
构造方法中:
ipc.server.read.threadpool.size
决定,默认为103、创建ZooKeeperWatcher
构造函数中生成如下持久节点:
/hbase/hbase/root-region-server/hbase/rs/table/draining/hbase/master/hbase/backup-masters/hbase/shutdown/hbase/unassigned/hbase/table94/hbase/table/hbase/hbaseid/hbase/splitlog
接下来看HMaster的run方法做了哪些事情。
1、总体过程
2、becomeActiveMaster方法:
zookeeper.session.timeout
,默认每3分钟检查一次)3、finishInitialization方法:
info server的启动移到构造函数了去了,这样可以早点通过Jetty服务器查看HMaster启动状态。
hbase.master.wait.on.regionservers.interval
)hbase.hlog.split.skip.errors=true
以忽略之)hbase.regionserver.hlog.splitlog.writer.threads
(默认为3)个线程,共使用128MB内存,启动这些写线程/hbase/.corrupt/
目录中/hbase/.oldlogs
中,然后删除原有的server目录.META.
表上未使用的region并回收在HMaster.finishInitialization
方法中触发了MasterFileSystem的构造方法,该类在HMaster类中会被以下类使用:
另外该类可以完成拆分log的工作:
/** * Override to change master's splitLogAfterStartup. Used testing * @param mfs */ protected void splitLogAfterStartup(final MasterFileSystem mfs){ mfs.splitLogAfterStartup(); }
这里主要是关心创建了哪些目录,其他用途暂不分析。
1、接下来,看其构造方法运行过程:
hbase.rootdir
配置${hbase.rootdir}/.tmp
fs.default.name
和fs.defaultFS
hbase.master.distributed.log.splitting
,如果需要,则创建SplitLogManagerhbase.server.thread.wakefrequency
调整${hbase.rootdir}
目录下是否有名为”hbase.id”的文件,如果没有则创建它,内容是随机生成的UUID(总长度36位,由5部份组成,用”-“分隔),如:6c43f934-37a2-4cae-9d49-3f5abfdc113dhbase.rootdir/-ROOT-
目录中是否存在tableinfo开头的文件,另外还创建了.tmp目录${hbase.rootdir}/.oldlogs
)不存在,则创建2、bootstrap方法运行过程:
经过上面分析之后,来看看zookeeper创建的一些目录分布式由哪个类来监控的:
/hbase
/hbase/root-region-server
:RootRegionTracker,监控root所在的regionserver/hbase/rs
:RegionServerTracker,监控regionserver的上线和下线/table/draining
:DrainingServerTracker,监听regionserver列表的变化/hbase/master
:在HMaster中建立,并且是一个短暂结点,结点的值是HMaster的ServerName:hostname,port,当前毫秒
/hbase/backup-masters
/hbase/shutdown
:ClusterStatusTracker,当HMaster启动之后,会将当前时间(Bytes.toBytes(new java.util.Date().toString())
)存到该节点/hbase/unassigned
:MetaNodeTracker/hbase/table94
/hbase/table
/hbase/hbaseid
:在HMaster.finishInitialization
方法中调用ClusterId.setClusterId建立,结点值是UUID/hbase/splitlog
在HMaster启动之后,${hbase.rootdir}
目录如下:
.├── -ROOT- //"-ROOT-"表名│ ├── ..tableinfo.0000000001.crc //crc校验文件│ ├── .tableinfo.0000000001│ ├── .tmp│ └── 70236052 //"-ROOT-"分区名│ ├── ..regioninfo.crc│ ├── .oldlogs //存放hlog文件│ │ ├── .hlog.1402551641526.crc│ │ └── hlog.1402551641526│ ├── .regioninfo //"-ROOT-"分区描述表件│ ├── .tmp│ └── info //列族名│ ├── .5037e69a0c244bd78945aaa333d0230a.crc│ └── 5037e69a0c244bd78945aaa333d0230a //存放".META."分区信息的StoreFile├── .META.│ └── 1028785192│ ├── ..regioninfo.crc│ ├── .oldlogs│ │ ├── .hlog.1402551641701.crc│ │ └── hlog.1402551641701│ ├── .regioninfo│ └── info├── .hbase.id.crc├── .hbase.version.crc├── .oldlogs├── .tmp├── hbase.id //集群uuid└── hbase.version //hbase版本
简单总结一下HMaster启动过程做了哪些事情:
转载地址:http://budvx.baihongyu.com/