Namenode startup of hadoop source code learning

 

Overview

hdfs mainly includes two types of nodes, namenode and datanode, so the startup of hdfs is the startup of these two types of nodes. namenode manages all datanode information, data block information, etc., which is the core of the entire hdfs, first start namenode, then Start the datanode again.

namenode formatting

The class of namenode is org.apache.hadoop.hdfs.server.namenode.NameNode, which is located in the hadooop-hdfs project. The entry method is the main method. The main method calls the static method createNameNode to create the namenode.

In the createNameNode method, operations such as formatting, upgrading, and startup are judged by the parameters in the switch. The code is as follows:

switch (startOpt) {
      case FORMAT: {
        boolean aborted = format(conf, startOpt.getForceFormat(),
            startOpt.getInteractiveFormat());
        terminate(aborted ? 1 : 0);
        return null; // avoid javac warning
      }
      case GENCLUSTERID: {
        System.err.println("Generating new cluster id:");
        System.out.println(NNStorage.newClusterID());
        terminate(0);
        return null;
      }
      case FINALIZE: {
        System.err.println("Use of the argument '" + StartupOption.FINALIZE +
            "' is no longer supported. To finalize an upgrade, start the NN " +
            " and then run `hdfs dfsadmin -finalizeUpgrade'");
        terminate(1);
        return null; // avoid javac warning
      }
      case ROLLBACK: {
        boolean aborted = doRollback(conf, true);
        terminate(aborted ? 1 : 0);
        return null; // avoid warning
      }
      case BOOTSTRAPSTANDBY: {
        String toolArgs[] = Arrays.copyOfRange(argv, 1, argv.length);
        int rc = BootstrapStandby.run(toolArgs, conf);
        terminate(rc);
        return null; // avoid warning
      }
      case INITIALIZESHAREDEDITS: {
        boolean aborted = initializeSharedEdits(conf,
            startOpt.getForceFormat(),
            startOpt.getInteractiveFormat());
        terminate(aborted ? 1 : 0);
        return null; // avoid warning
      }
      case BACKUP:
      case CHECKPOINT: {
        NamenodeRole role = startOpt.toNodeRole();
        DefaultMetricsSystem.initialize(role.toString().replace(" ", ""));
        return new BackupNode(conf, role);
      }
      case RECOVER: {
        NameNode.doRecovery(startOpt, conf);
        return null;
      }
      case METADATAVERSION: {
        printMetadataVersion(conf);
        terminate(0);
        return null; // avoid javac warning
      }
      case UPGRADEONLY: {
        DefaultMetricsSystem.initialize("NameNode");
        new NameNode(conf);
        terminate(0);
        return null;
      }
      default: {
        DefaultMetricsSystem.initialize("NameNode");
        return new NameNode(conf);
      }
    }

The namenode needs to be formatted before starting. The main purpose of the format is to initialize the data directory of the namenode, initialize the id, version of the cluster, etc., and write the corresponding property file in the configured directory.

The main method of formatting is the format method in the namenode. Here, the corresponding configuration is mainly read from the configuration file, some corresponding checks are made, and then two very core classes of hdfs, FSImage and FSNamesystem, are constructed.

( FSImage: The metadata of the hdfs system is stored in the hard disk, and the image of the hdfs at a certain time is saved, and the subsequent real-time operations are recorded in the FSEditLog class.

FSNamesystem : FSNamesystem does the actual bookkeeping work for the DataNode, this note explains the function of FSNamesystem very well

FSImage fsImage = new FSImage(conf, nameDirsToFormat, editDirsToFormat);
    try {
      FSNamesystem fsn = new FSNamesystem(conf, fsImage);
      fsImage.getEditLog().initJournalsForWrite();

      if (!fsImage.confirmFormat(force, isInteractive)) {
        return true; // aborted
      }

      fsImage.format(fsn, clusterId);
    } catch (IOException ioe) {
      LOG.warn("Encountered exception during format: ", ioe);
      fsImage.close();
      throw ioe;
    }

Finally, the FSImage#format method is called to format the operation

void format(FSNamesystem fsn, String clusterId) throws IOException {
    long fileCount = fsn.getTotalFiles();
    // Expect 1 file, which is the root inode
    Preconditions.checkState(fileCount == 1,
        "FSImage.format should be called with an uninitialized namesystem, has " +
        fileCount + " files");
    NamespaceInfo ns = NNStorage.newNamespaceInfo();
    LOG.info("Allocated new BlockPoolId: " + ns.getBlockPoolID());
    ns.clusterID = clusterId;
    
    storage.format(ns);//进行namenode所有的目录的格式化,写属性文件
    editLog.formatNonFileJournals(ns);//初始化编辑日志
    saveFSImageInAllDirs(fsn, 0);//初始化fsimage
  }

start of namenode

Overall process

namenode的启动是直接进入了了上述switch中的default选项,使用配置文件调用构造方法构造了namenode对象

在构造方法中,首先进行了一系列的赋值操作,然后调用initialize(Configuration conf)来初始化namenode

首先通过startHttpServer来启动一个web服务器,我们可以通过这个web服务器来查询hdfs的各种使用情况,其次用loadNamesystem(conf)从磁盘加载元数据到内存中,然后 rpcServer = createRpcServer(conf);来初始化namenode的rpc服务。最后startCommonServices(conf);来启动服务,这个时候namnode的各项服务就初始化完成了。

服务启动流程详解

通过FSNamesystem中的startCommonServices方法来启动服务 namesystem.startCommonServices(conf, haContext); 然后调用了org.apache.hadoop.hdfs.server.blockmanagement.BlockManager.activate(Configuration)

public void activate(Configuration conf) {
    pendingReplications.start();
    datanodeManager.activate(conf);
    this.replicationThread.start();
    this.blockReportThread.start();
  }

pendingReplications

pendingReplications.start()构造了一个PendingReplicationMonitor线程并且启动, PendingReplicationMonitor的功能参考以下注释

/*
   * A periodic thread that scans for blocks that never finished
   * their replication request.
   */
  class PendingReplicationMonitor implements Runnable {
      .................
  }

datanodeManager

datanodeManager.activate(conf);启动了监控线程和心跳处理线程

void activate(final Configuration conf) {
    decomManager.activate(conf);
    heartbeatManager.activate(conf);
  }

replicationThread

初始化副本的监控线程ReplicationMonitor并启动

blockReportThread

初始化块处理线程,对datanode上报的数据块进行处理,此线程为后台线程 setDaemon(true);

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326422127&siteId=291194637