HDFS源碼解析(一)

廢話不多說,直接進入org.apache.hadoop.hdfs.server.namenode包下NameNode類的main方法

public static void main(String argv[]) throws Exception {
    if (DFSUtil.parseHelpArgument(argv, NameNode.USAGE, System.out, true)) {
      System.exit(0);
    }

    try {
      StringUtils.startupShutdownMessage(NameNode.class, argv, LOG);
      NameNode namenode = createNameNode(argv, null);
      if (namenode != null) {
        namenode.join();
      }
    } catch (Throwable e) {
      LOG.fatal("Exception in namenode join", e);
      terminate(1, e);
    }
  }

DFSUtil的parseHelpArgument方法用於解析輸入的命令行參數。接下來看try,catch語句塊:

StringUtils的startupShutdownMessage方法字面很容易看出是打印啓動關閉信息;NameNode

的主要工作由createNameNode方法完成,我們進入createNameNode可以發現主要是switch語句塊,我們重點看下關於格式化format

case FORMAT: {
       boolean aborted = format(conf, startOpt.getForceFormat(),
           startOpt.getInteractiveFormat());
       terminate(aborted ? 1 : 0);
       return null; // avoid javac warning
     }

然後進入format方法,每一步的註釋寫在代碼後面,自己看

private static boolean format(Configuration conf, boolean force,
      boolean isInteractive) throws IOException {
    String nsId = DFSUtil.getNamenodeNameServiceId(conf); // 獲取nameserviceid,在hadoop ha中配置
    String namenodeId = HAUtil.getNameNodeId(conf, nsId); // 獲取namenodeid,
    initializeGenericKeys(conf, nsId, namenodeId);
    checkAllowFormat(conf); // 判斷是否允許格式化,也就是你不能把正在運行的hdfs給格了

    if (UserGroupInformation.isSecurityEnabled()) { // 看到UserGroupInformation,我們知道這是hdfs系統權限相關的,
                                                    // 判斷是否使用Kerberos驗證
      InetSocketAddress socAddr = getAddress(conf);
      SecurityUtil.login(conf, DFS_NAMENODE_KEYTAB_FILE_KEY,
          DFS_NAMENODE_USER_NAME_KEY, socAddr.getHostName());
    }

    /*
    獲取hdfs-site.xml中dfs.namenode.name.dir設置的路徑,如/home/hadoop/dfs/name
    用於存儲文件系統命名空間鏡像
     */
    Collection<URI> nameDirsToFormat = FSNamesystem.getNamespaceDirs(conf);
    /*
    獲取hdfs-site.xml中dfs.namenode.shared.edits.dir設置的路徑,如果使用的hadoop的ha配置,
    那麼值可以爲qjournal://node1:8485;node2:8485;node3:8485/clusterid,其中clusterid是dfs.nameservices配置的值
     */
    List<URI> sharedDirs = FSNamesystem.getSharedEditsDirs(conf);
    List<URI> dirsToPrompt = new ArrayList<URI>();
    dirsToPrompt.addAll(nameDirsToFormat);
    dirsToPrompt.addAll(sharedDirs);
    List<URI> editDirsToFormat = 
                 FSNamesystem.getNamespaceEditsDirs(conf);

    // if clusterID is not provided - see if you can find the current one
    String clusterId = StartupOption.FORMAT.getClusterId();
    if(clusterId == null || clusterId.equals("")) {
      //Generate a new cluster id
      clusterId = NNStorage.newClusterID();
    }
    System.out.println("Formatting using clusterid: " + clusterId);
    // 關於文件系統的創建,日後會詳細分析
    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;
    }
    return false;
  }

回到NameNode的main方法,namenode.join最終啓動的是RPC.Server serviceRpcServer,RPC.ServerclientRpcServer兩大線程。

serviceRpcServer監聽來自DataNodes的請求,clientRpcServer監聽來自客戶端的請求。













發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章