hbase-daemon.sh中停止RS的脚本如下:
if [ -f $pid ]; then # kill -0 == see if the PID exists if kill -0 `cat $pid` > /dev/null 2>&1; then //判断进程是否存在 echo -n stopping $command echo "`date` Terminating $command" >> $loglog kill `cat $pid` > /dev/null 2>&1 //kill,RS接受到stop信号,开始处理stop工作 while kill -0 `cat $pid` > /dev/null 2>&1; do //等待RS进程退出,退出前每隔1秒打印一个”.” echo -n "." sleep 1; done rm $pid echo else retval=$? echo no $command to stop because kill -0 of pid `cat $pid` failed with status $retval fi else echo no $command to stop because no pid file $pid fi ;; |
在启动RS时会使用HRegionServer对象通过Runable.addShutdownHook()方法注册一个jvm退出钩子,当RS进程被非强制kill时会执行HRegionServer的stop()方法,在stop()方法中重点是设置valotile变量stopped=true,在HRegionServer的run()方法的while循环中,发现stopped=true则退出循环,执行stop工作,比如:关闭RPC服务,关闭Region,关闭compact和split等线程池(最长等待60s),从zk中清除对应的节点等工作。
由于RS中很多线程,包括HRegionServer自身就是一个Runable的实现类,这些线程必须确保执行完成,hbase是通过线程的join()方法实现的,当调用join()方法后,会阻塞退出钩子的线程,直到所有线程都执行完成才会完成真正的退出,操作系统才会完成kill。
关于jvm的退出钩子在使用时需注意两点:
1、在设置stop变量后,需通过join()或者一些方式确保当前任务已经执行完
2、如果线程中有wait() 或者sleep(),则需停止等待或者休眠,避免无谓的时间消耗影响退出速度。