衔接
在上一篇文章中,HMasterCommandLine类中在startMaster();方法中
java
// 这里除了启动HMaster之外,还启动一个HRegionServer
LocalHBaseCluster cluster = new LocalHBaseCluster(conf, mastersCount, regionServersCount,
LocalHMaster.class, HRegionServer.class);
// 这里getMaster 会获取到HMaster吧
((LocalHMaster)cluster.getMaster(0)).setZKCluster(zooKeeperCluster);
cluster.startup();
waitOnMasterThreads(cluster);
使用了 cluster.startup(); 对HBase的主要进程进行启动
java
public void startup() throws IOException {
JVMClusterUtil.startup(this.masterThreads, this.regionThreads);
}
1. JVMClusterUtil.java
public static String startup(final List<JVMClusterUtil.MasterThread> masters,
final List<JVMClusterUtil.RegionServerThread> regionservers) throws IOException
这个函数上面,显示完成了HMaster的线程初始化,然后等到HMaster的线程初始化后,又调用了HRegionServer的线程初始化,但我发现HMaster线程在执行完run方法后,在run方法最后还执行了一遍super.run(),HMaster多执行了一次HRegionServer.run方法的目的是为了?
ChatGPT回答的可能原因
- 继承自公共的父类:
- 在HBase的实现中,
HMaster
和HRegionServer
都可能继承自一个共同的父类或实现了相同的接口(例如Thread
或Runnable
接口),该父类可能定义了一个run()
方法,用于执行一些通用的逻辑。 - 当
HMaster
在执行自己的run()
方法后调用super.run()
时,它可能是在执行父类中的通用逻辑。这种逻辑可能与线程的基础设施或资源管理有关,而不仅仅是特定于HRegionServer
的逻辑。
HMaster
和HRegionServer
共享某些功能:
HMaster
和HRegionServer
虽然在职责上不同,但它们可能共享某些基础功能,比如网络通信、线程管理、资源分配等。父类中的run()
方法可能封装了这些通用功能,因此HMaster
在完成自己的工作后,调用super.run()
来确保这些共享功能得以执行。- 这可能解释了为什么在
HMaster
的run()
方法之后还要调用super.run()
:这是为了确保即使是HMaster
,也能够执行一些HRegionServer
和HMaster
共享的初始化或管理任务。
- 确保线程生命周期的完整性:
super.run()
的调用可能是为了确保线程的生命周期管理符合预期。例如,在某些实现中,父类的run()
方法可能会处理线程的启动、暂停、恢复、终止等状态。如果不调用super.run()
,可能会导致线程的状态管理不完整或不正确。
经过在HRegionServer.run 方法print 测试发现,HRegionServer.run在HMaster启动时调用了一次,在HR egionServer 线程启动时又调用了一次
带着这三个内容,我们去看HMaster run方法之后的HRegionServer run方法
2. HMaster.run() 方法
java
public void run() {
try {
//用于控制是否在本地测试时启动一个完整的HBase集群
if (!conf.getBoolean("hbase.testing.nocluster", false)) {
Threads.setDaemonThreadRunning(new Thread(() -> {
try {
// 定义端口
int infoPort = putUpJettyServer();
// 启动MasterManager
startActiveMasterManager(infoPort);
} catch (Throwable t) {
// Make sure we log the exception.
String error = "Failed to become Active Master";
LOG.error(error, t);
// Abort should have been called already.
if (!isAborted()) {
abort(error, t);
}
}
}), getName() + ":becomeActiveMaster");
}
// Fall in here even if we have been aborted. Need to run the shutdown services and
// the super run call will do this for us.
super.run();
HMaster的接口只是调用了startActiveMasterManager(infoPort); 对Master的一些基础内容进行初始化(具体内容请看HBase源码阅读(一)),然后又调用了一次HRegionServer的run方法
3. HRegionServer run方法
- HMaster.java.,HMaster run()线程启动临近结束后,再调用HRegionServer进程
仔细看HRegionServer.run方法,主要涉及HRegionServer的运行和启动
所以上一章节中的问题应该是第二个选型
HMaster
和HRegionServer
共享某些功能:
HMaster 比HRegionServer在HMaster.run中多了一些内容
HMaster
和HRegionServer
虽然在职责上不同,但它们可能共享某些基础功能,比如网络通信、线程管理、资源分配等。父类中的run()
方法可能封装了这些通用功能,因此HMaster
在完成自己的工作后,调用super.run()
来确保这些共享功能得以执行。- 这可能解释了为什么在
HMaster
的run()
方法之后还要调用super.run()
:这是为了确保即使是HMaster
,也能够执行一些HRegionServer
和HMaster
共享的初始化或管理任务。
4. HRegionServer.handleReportForDutyResponse()
简单过一下,用来启动所有的服务器线程
- 设置hostname
- 在zookeeper中设置Znode
- 初始化文件系统
- 设置已经初始化的副本和WAL
- 设置线程名称
- 启动暂停监视器
- 启动复制服务(启动复制源和接收器处理程序。)
- log zk的信息,唤醒其他所有等待该RegionServer 启动的其他节点
3.1 暂停监视器
JvmPauseMonitor
的作用和功能
- 监控JVM暂停事件 :
JvmPauseMonitor
通过定期检查系统时间的变化来判断是否发生了JVM暂停。它会设置一个定时器,每隔一段固定的时间去检测系统的时间戳。如果时间戳的变化超过预期值,这通常意味着JVM暂停事件发生了。
- 检测长时间的GC停顿 :
- JVM暂停最常见的原因之一是垃圾收集(GC),尤其是Full GC或长时间的Stop-the-World(STW)事件。
JvmPauseMonitor
可以帮助检测这些事件,因为它们可能会导致HBase的RegionServer或者HMaster的服务性能下降,甚至导致客户端请求超时。
- JVM暂停最常见的原因之一是垃圾收集(GC),尤其是Full GC或长时间的Stop-the-World(STW)事件。
- 日志记录和报警 :
- 当
JvmPauseMonitor
检测到异常的暂停(通常超过一定阈值,例如几百毫秒或更长),它会记录警告日志。日志中会包括暂停的时长、可能的原因等信息。这有助于运维人员监控和分析系统的性能问题,尤其是在垃圾回收引起的问题上。
- 当
- 提高系统可靠性 :
- 通过监控和记录JVM暂停,
JvmPauseMonitor
帮助识别出可能影响HBase性能的问题,允许系统管理员采取预防或修复措施。尽管JvmPauseMonitor
本身不会直接解决这些问题,但它提供了有价值的诊断信息,帮助识别和缓解性能瓶颈。
- 通过监控和记录JVM暂停,