第二篇 hbase2.4.2 源码分析 RegionServer启动流程


前言

1.看什么? 看HRegionServer类说明 看main()入口 看初始化了哪些重要组件 如何进行远程调用 如何看:看过程中画图,或者把方法的调用关系,对象的调用按照调用关系记录下来,本文按照第二种方式进行编写

一、HRegionServer类继承关系

看什么?
看类说明,看继承关系
从哲学角度看:这是性质问题
HRegionServer 是个线程,实现 RegionServerServices, LastSequenceId, ConfigurationObserver 几个接口,既然是线程,肯定有run方法

/**
 * HRegionServer makes a set of HRegions available to clients. It checks in with
 * the HMaster. There are many HRegionServers in a single HBase deployment.
 */
@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.TOOLS)
@SuppressWarnings({ "deprecation"})
public class HRegionServer extends Thread implements
    RegionServerServices, LastSequenceId, ConfigurationObserver {

二、HRegionServer.main入口分析

1.main入口

  /**
   * @see org.apache.hadoop.hbase.regionserver.HRegionServerCommandLine
   */
  public static void main(String[] args) {
    LOG.info("STARTING executorService " + HRegionServer.class.getSimpleName());
    VersionInfo.logVersion();
    Configuration conf = HBaseConfiguration.create();
    @SuppressWarnings("unchecked")
    Class<? extends HRegionServer> regionServerClass = (Class<? extends HRegionServer>) conf
        .getClass(HConstants.REGION_SERVER_IMPL, HRegionServer.class);

    new HRegionServerCommandLine(regionServerClass).doMain(args);
  }
HRegionServerCommandLine.doMain()如下
  /**
   * Parse and run the given command line. This may exit the JVM if
   * a nonzero exit code is returned from <code>run()</code>.
   */
  public void doMain(String args[]) {
    try {
      //核心代码,为什么是核心代码?除了它,还有其他值得看的吗?
      int ret = ToolRunner.run(HBaseConfiguration.create(), this, args);
      if (ret != 0) {
        System.exit(ret);
      }
    } catch (Exception e) {
      LOG.error("Failed to run", e);
      System.exit(-1);
    }
  }
  
  public static int run(Configuration conf, Tool tool, String[] args) throws Exception {
    if (CallerContext.getCurrent() == null) {
      CallerContext ctx = (new Builder("CLI")).build();
      CallerContext.setCurrent(ctx);
    }

    if (conf == null) {
      conf = new Configuration();
    }

    GenericOptionsParser parser = new GenericOptionsParser(conf, args);
    tool.setConf(conf);
    String[] toolArgs = parser.getRemainingArgs();
    //在这里真正调用,org.apache.hadoop.util.Tool竟然是Hadoop包的,我在想,为什么,不直接在hbase包下启动就好了,吐槽。。。
    return tool.run(toolArgs);
  }
  tool就是:  HRegionServerCommandLine, 找HRegionServerCommandLine.run()

 @Override
  public int run(String args[]) throws Exception {
    if (args.length != 1) {
      usage(null);
      return 1;
    }

    String cmd = args[0];

    if ("start".equals(cmd)) {
    //启动代码,追进去看看
      return start();
    } else if ("stop".equals(cmd)) {
      System.err.println(
        "To shutdown the regionserver run " +
        "hbase-daemon.sh stop regionserver or send a kill signal to " +
        "the regionserver pid");
      return 1;
    } else {
      usage("Unknown command: " + args[0]);
      return 1;
    }
  }

//到达启动流程
private int start() throws Exception {
    Configuration conf = getConf();
    TraceUtil.initTracer(conf);
    try {
      // If 'local', don't start a region server here. Defer to
      // LocalHBaseCluster. It manages 'local' clusters.
      //local模式
      if (LocalHBaseCluster.isLocal(conf)) {
        LOG.warn("Not starting a distinct region server because "
            + HConstants.CLUSTER_DISTRIBUTED + " is false");
      } else {
      //集群模式
        logProcessInfo(getConf());
        HRegionServer hrs = HRegionServer.constructRegionServer(regionServerClass, conf);
        hrs.start(); //启动,触发HRegionServer的run方法
        hrs.join();  //等待线程结束
        if (hrs.isAborted()) {
          throw new RuntimeException("HRegionServer Aborted");
        }
      }
    } catch (Throwable t) {
      LOG.error("Region server exiting", t);
      return 1;
    }
    return 0;
  }

2.HRegionServer.run()分析 核心服务都在这启动

代码如下(示例):

run()
 preRegistrationInitialization
   setupClusterConnection()
     初始化clusterConnection和MetaTableLocator
   initializeZooKeeper()
   initializeThreads()

   跟master进行注册
   RegionServerStartupResponse w = reportForDuty();
    handleReportForDutyResponse()处理master返回的响应
     createMyEphemeralNode() 在zk的/rs目录进行注册(创建临时节点)
     initializeFileSystem();
     setupWALAndReplication();
     startReplicationService()
     JvmPauseMonitor() jvm fullGC停顿检测线程
     startServices() --启动很多服务和线程
       HeapMemoryManager管理器启动

三、 HRegionServer和master的rpc如何调用?

RegionServerStartupResponse w = reportForDuty();
  
          RegionServerStartupRequest.Builder request = RegionServerStartupRequest.newBuilder();
      if (!StringUtils.isBlank(useThisHostnameInstead)) {
        request.setUseThisHostnameInstead(useThisHostnameInstead);
      }
      request.setPort(port);
      request.setServerStartCode(this.startcode);
      request.setServerCurrentTime(now);
        这里的rss就是跟master交互的接口
      result = rss.regionServerStartup(null, request.build());
这种request.newBuilder().build() builder模式生成请求,然后进行rpc交互,采用google,gRpc协议通信
那怎么知道,哪个类接收到regionserver发起的rpc请求?     直接搜索regionServerStartup方法,看看有哪个类实现了该方法

发现是MasterRpcServices实现了,查看方法实现,只是把regionserver的信息放到一个map里面保存

调用栈:
 regionServerStartup 
  checkAndRecordNewServer
   recordNewServerWithLock
  /**
   * Adds the onlineServers list. onlineServers should be locked.
   * @param serverName The remote servers name.
   */
  void recordNewServerWithLock(final ServerName serverName, final ServerMetrics sl) {
    LOG.info("Registering regionserver=" + serverName);
    this.onlineServers.put(serverName, sl);
    this.rsAdmins.remove(serverName);
  }

在这里插入图片描述

总结

regionserver启动 : 构造器初始化,线程启动,run()方法调用,启动一堆看不懂服务。。。 rpc调用: 使用 gRpc框架
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值