在安装HBase的时候需要配置一些参数,这些参数在HBase启动的时候发挥着怎样的作用,如何影响的HBase的运行,出现启动错误时如何快速定位错误的位置。在解决这些问题之前,先从源码的角度分析一下HBase的启动流程,了解HBase是怎么启动的。
启动流程概述
启动HBase会执行start-hbase.sh,然后脚本会先执行hbase-config.sh,做一系列的配置设置,包括常用路径、regionservers和backup-masters列表、常用端口等。在hbase-config.sh中会执行hbase-env.sh,主要对JAVA的环境参数、ssh,、pid路径等进行配置。start-hbase.sh最后会根据hbase.cluster.distributed来确定启动模式,分为本地和分布式。
分布式启动HBase,使用hbase-daemons.sh逐步启动zookeeper、master、regionserver、master-backup。具体会调用相关的脚本(如zookeeper会调用zookeerper.sh)来进行环境的配置和登录到相关的机器节点上执行hbase-daemon.sh。
hbase-daemon.sh的职责就是启动各个进程,在启动过程中会先做进程判断,日志滚动等准备,最后执行启动命名,逐步的启动各个节点上的进程。在启动过程中,会在屏幕中打印启动信息。
执行流程图:
具体启动流程
接下来分析每一步的源码,了解整个执行的过程。
start-hbase.sh
作为HBase启动的入口,在执行hbase-config.sh设置完运行的环境变量后,会执行命令,获取hbase.cluster.distributed的值来确定HBase的启动模式。
具体的代码实现:
hbase.cluster.distributed在hbase-site.xml中进行配置,默认值为false。false将启动standalone模式,true将启动distributed模式,在配置分布式的时候需要改成true。
standalone模式将会在一个JVM中运行所有的HBase和zookeeper。distributed模式会逐渐启动zookeeper、master、regionserver、master-backup等进程和节点。在启动节点时,$commandToRun有两种选择,可以是start(默认),还可以是autorestart。
hbase-config.sh
由于启动的脚本如hbase-daemon.sh,zookeerper.sh等都不是在一台机器上运行,因此每个脚本在执行前都会先执行一下hbase-config.sh来配置运行时的环境变量。
在hbase-config.sh中首先会检查hbase-config.sh是否是一个软连接,找到hbase-config.sh的真实路径。然后设置HBASE_HOME,判断是否指定了hbase的配置文件路径,如果没有将采用默认的配置文件路径。
脚本会设置一些默认的参数,包括HBASE_CONF_DIR、HBASE_REGIONSERVERS、HBASE_BACKUP_MASTERS、HBASE_THRIFT_JMX_OPTS等,然后执行hbase-env.sh配置HBase的AVA的运行环境和ssh参数等。程序会判断是否设置HBASE_REGIONSERVER_MLOCK为true,这个主要是判断系统是否使用了mlock来锁住内存,防止这段内存被操作系统swap掉。这将阻止Linux 将这个内存页调度到交换空间(swap space),即使该程序已有一段时间没有访问这段空间。最后如果检测到了JAVA_HOME后,程序将会继续运行。
hbase-env.sh
hbase-env.sh中设置了HBase运行中的一些重要的JVM参数,后续在进行HBase调优时会用到这些参数。除此之外还有一些进程优先级,SSH参数等。主要参数如下:
1、JAVA_HOME
JAVA的JDK路径,需要java 1.7以上
2、HBASE_HEAPSIZE
堆的最大使用量。默认情况下是JVM默认值
3、HBASE_OFFHEAPSIZE
如果打算使用堆缓存,可以设置该值。例如,要分配8G的offheap,将值设置为“8G”。
4、HBASE_OPTS
默认为”-XX:+UseConcMarkSweepGC”
使用CMS收集器对年老代进行垃圾收集,CMS收集器通过多线程并发进行垃圾回收,尽量减少垃圾收集造成的停顿。
参考文档:Java内存与垃圾回收调优 - ImportNew
5、PermSize设置非堆内存初始值
仅仅是JDK7需要配置,JDK8+后就不需要
6、HBASE_MASTER_OPTS、HBASE_REGIONSERVER_OPTS
配置非堆内存,初始分配的堆内存,大允许分配的堆内存,按需分配
参考文档:Xms Xmx PermSize MaxPermSize 区别 - 残星 - 博客园
7、java回收机制,分别配置sever和client端
HBase会在启动的时候讲Java的一些配置打印到.out日志中
8、HBASE_MANAGES_ZK
是否由它自己的zookpeer来管理,一般使用单独的zookeeper集群来管理hbase。
9、HBASE_PID_DIR
pid的路径,默认_tmp目录下,但_tmp中的文件易失,导致找不到pid文件,最后配置一个其它稳定的文件。
10、HBASE_NICENESS
守护进程的调度优先级
11、HBASE_IDENT_STRING
标志hbase实例的字符串,默认情况下为当前用户,会在创建pid,log等文件时使用
12、HBASE_BACKUP_MASTERS
在backup-masters中配置配置bakcup的master,当一台master宕机后,zookeeper会在backup中选择一个。默认backup-masters是不存在的,需要自己新建
13、HBASE_SSH_OPTS
ssh配置,如果ssh的端口不是22,可以进行设置HBASE_SSH_OPTS=”-p xxx”,后面再启动各个进程的时候会用到,如:
14、HBASE_LOG_DIR
hbase的日志路径
hbase-daemons.sh
hbase-daemons.sh比较简单,主要根据要启动的进程,生成好远程执行命令remote_cmd,然后做分发。
zookeepers.sh
如果HBASE_MANAGES_ZK为true,表示hbase使用自带的zookeeper集群,如果不是,需要去加载用户自定义的配置。
在org.apache.hadoop.hbase.zookeeper.ZKServerTool
中通过readZKNodes获取到zookeerper的节点地址。
其会在conf目录下搜寻zoo.cfg文件,加载zookeeper的配置,如果没有则会去hbase-site.xml中加载zookeeper的配置,包括hbase.zookeeper.quorum,hbase.zookeeper.property.clientPort,hbase.zookeeper.property.dataDir等参数。因此zookeeper的信息可以在zoo.cfg中配置,也可以在hbase-site.xml中进行配置。
master-backup.sh
在master-backup.sh中,首先会获取到 backup-masters列表,然后登陆到节点上去以backup的方式启动master
启动后zookeeper会自动选取一个master作为active,其它的都是backup。
regionservers.sh
首先获取到regionservers列表,默认在conf/regionservers中进行设置,如果regionservers是默认的localhost,则会在本地启动regionserver。设置成distributed后,会在各个节点上启动regionserver节点。$”${@// /\\ }“
会将命令中将所有的\替换成为空格。
hbase-daemon.sh
前面的脚本都是做的准备工作,启动各个节点最后都是由hbase-daemon.sh来完成的。因此hbase-daemon.sh应该是最重要的脚本,负责启动前的环境清理,日志滚动以及进程启动等工作。
hbase-daemon.sh支持start|stop|restart|autorestart|foreground_start,5种启动方式,可以单独用来管理节点,如启动regionserver:hbase-daemon.sh start regionserver
经过一系列的日志文件路径设置后,开始执行start过程。
首先check_before_start检查要启动的进程是否存在,如果存在就会发出$command running as process cat $HBASE_PID. Stop it first
的提示。看到这个提示,应该到该机器节点上去查询一下该进程的情况。
接着进行日志的滚动,如果日志文件存在就进行1->5的滚动,因此我们能够看到logs下有编号1到5的日志文件。默认情况是不会输出GC日志的,可以在hbase-env.sh中开启SERVER_GC_OPTS,CLIENT_GC_OPTS配置,才会输出GC日志。
随后会使用foreground_start来启动进程
当脚本收到SIGHUP SIGINT SIGTERM EXIT的信号时,trap命令执行cleanAfterRun,kill掉已经存在的进程,然后告诉zk删除有问题的节点。
从代码中可以看到,最后启动脚本使用hbase命令来启动的,在hbase中将会进行一系列的设置如日志,lib库,执行类等,最终会运行exec "$JAVA" -Dproc_$COMMAND -XX:OnOutOfMemoryError="kill -9 %p" $HEAP_SETTINGS $HBASE_OPTS $CLASS "$@"
来启动相应的进程。执行成功后,可以ps -ef|grep 进程名
来查看最后是执行了什么命令来启动进程的,如查看HMaster如何启动的ps -ef|grep HMaster
,就会列出具体的进程信息。
总结
HBase在启动过程中,会先配置大量的参数,重要的有JVM参数,regionserver,master-backup列表,路径等。分析一遍启动的过程后,明白了哪些参数在什么位置使用,起到了什么样的作用,能够为HBase的运维提供一个指导。最后自己也学到了很多shell编程的知识。