跟我一起读Hadoop源码——HDFS篇(01)

1 篇文章 0 订阅
1 篇文章 0 订阅

写在前面的话

这里是跟我一起读Hadoop源码系列的第一篇,主要记录作者在读Hadoop源码的过程

软件版本

-Hadoop2.6.0

读前知识

-了解RPC编程
-了解Java基础


从NameNode开始

在Hadoop的所有文章中都讲述了Namenode的作用,所以这里就不做过多的说明,直接
来读它的源码。
在读一个类时从哪里下手比较好呢,当然是注释。在大多开源软件的主要代码中都会
给出比较详细的注释我们就从这里入手。

/**********************************************************
 * NameNode serves as both directory namespace manager and
 * "inode table" for the Hadoop DFS.  There is a single NameNode
 * running in any DFS deployment.  (Well, except when there
 * is a second backup/failover NameNode, or when using federated NameNodes.)
 *
 * The NameNode controls two critical tables:
 *   1)  filename->blocksequence (namespace)
 *   2)  block->machinelist ("inodes")
 *
 * The first table is stored on disk and is very precious.
 * The second table is rebuilt every time the NameNode comes up.
 *
 * 'NameNode' refers to both this class as well as the 'NameNode server'.
 * The 'FSNamesystem' class actually performs most of the filesystem
 * management.  The majority of the 'NameNode' class itself is concerned
 * with exposing the IPC interface and the HTTP server to the outside world,
 * plus some configuration management.
 *
 * NameNode implements the
 * {@link org.apache.hadoop.hdfs.protocol.ClientProtocol} interface, which
 * allows clients to ask for DFS services.
 * {@link org.apache.hadoop.hdfs.protocol.ClientProtocol} is not designed for
 * direct use by authors of DFS client code.  End-users should instead use the
 * {@link org.apache.hadoop.fs.FileSystem} class.
 *
 * NameNode also implements the
 * {@link org.apache.hadoop.hdfs.server.protocol.DatanodeProtocol} interface,
 * used by DataNodes that actually store DFS data blocks.  These
 * methods are invoked repeatedly and automatically by all the
 * DataNodes in a DFS deployment.
 *
 * NameNode also implements the
 * {@link org.apache.hadoop.hdfs.server.protocol.NamenodeProtocol} interface,
 * used by secondary namenodes or rebalancing processes to get partial
 * NameNode state, for example partial blocksMap etc.
 **********************************************************/

这段注释说明了NameNode的用途和实现的功能,本人英文不好在这里就不翻译了。


下面来看一下NameNode类的定义:

  @InterfaceAudience.Private
  public class NameNode implements NameNodeStatusMXBean {
    //些处省略类体定义

  }

O-O不是说好的实现了那么多接口吗,怎么就实现了一个接口,是不是有接口继承那再来看一
下这个接口的内容吧:

/**
 * This is the JMX management interface for NameNode status information
 * 这是一个被JMX管理的接口来监控NameNode的状态
 */
@InterfaceAudience.Public
@InterfaceStability.Evolving
public interface NameNodeStatusMXBean {

  /**
   * Gets the NameNode role.
   * 获取NameNode的角色
   * 角色分为 NAMENODE("NameNode"),BACKUP("Backup Node"),CHECKPOINT("Checkpoint Node");
   * @return the NameNode role.
   */
  public String getNNRole();

  /**
   * Gets the NameNode state.
   * 获取NameNode的状态这个是对HA来说的
   * 可以有initializing,active,standby和stopping
   * @return the NameNode state.
   */
  public String getState();

  /**
   * Gets the host and port colon separated.
   * 获取NameNode的IP和端口号(localhost:9000) 
   * @return host and port colon separated.
   */
  public String getHostAndPort();

  /**
   * Gets if security is enabled.
   * 获取是否开启了安全验证
   * @return true, if security is enabled.
   */
  public boolean isSecurityEnabled();
}

木有,那它是怎么实现上面所说的方法呢。来看看它的成员变量吧!

需要说明的是在Java中类实现某个功能可以通过继承或者组合的方法
来实现

  //NameNode核心成员变量用来管理元数据
  protected FSNamesystem namesystem; 
  //保存配置文件的信息
  protected final Configuration conf;
  //保存NameNode的角色信息
  protected final NamenodeRole role;
  //保存NameNode的状态
  private volatile HAState state;
  //是否开启了高可用(HA)
  private final boolean haEnabled;
  //高可用上下文
  private final HAContext haContext;
  //NameNode核心成员变量提供RPC服务
  private NameNodeRpcServer rpcServer;

这里只是简单列出了几个比较重要的成员变量来做分析,其它的有兴趣可以自己阅读源码
其中namesystem和rpcServer是核心成员,NameNode的大部分功能都由这两个成员变量实现
namesystem:实现对DataNode、Block的管理以及读写日志
rpcServer:提供RPC服务是DataNode和NameNode通信和外部命令管理NameNode的窗口
以上两个成员变量的分析将另开文章
conf:保存NameNode的配置信息,NameNode会根据这些信息来初始化自己并开始运行

主要来自hdfs-site.xml

role:保存当前NameNode的角色NAMENODE提供元数据管理的服务,BACKUP提供一个备用的NameNode并且
提供合并fsimage和edits的功能不同的是不用从NAMENODE下载(它本身的状态和NAMENODE一致)
CHECKPOINT用来替代SecondNameNode的用来合并fsimage和edits


NameNode除了在集群运行时提供管理集群和元数据的功能外还提供以下功能
-FORMAT:格式化HDFS文件系统
-GENCLUSTERID: 生成一个新的集群ID
-FINALIZE:定版本,在升级完成并且通过测试后执行这个命令(这个命令被hdfs dfsadmin -finalizeUpgrade代替了)
-ROLLBACK:返回升级前的版本(注意:需要御载新版本并安装老版本)
-BOOTSTRAPSTANDBY:同步active节点的快照(配置完HA需要运行这个命令)
-INITIALIZESHAREDEDITS:向备用节点共享一组edits日志
-BACKUP:以BACKUP的角色启动
-CHECKPOINT:以CHECKPOINT的角色启动
-RECOVER:覆盖元数据
-METADATAVERSION:验证配置的正确性并打印版本信息
-UPGRADEONLY:以升级的方式启动
-Default:正常以NAMENODE启动

以上命令在Hadoop的文档中都有说明可以查看对应的详细说明,只是说明这些命令是在这里实现的。

以下是NameNode启动部分的源码
主方法部分:

  public static void main(String argv[]) throws Exception {
    //检查参数的合法性 在以NAMENODE启动时不需要传参数
    if (DFSUtil.parseHelpArgument(argv, NameNode.USAGE, System.out, true)) {
      System.exit(0);
    }

    try {
      StringUtils.startupShutdownMessage(NameNode.class, argv, LOG);
      //根据参数启动对应的NameNode
      NameNode namenode = createNameNode(argv, null);
      if (namenode != null) {
        namenode.join();
      }
    } catch (Throwable e) {
      LOG.fatal("Failed to start namenode.", e);
      terminate(1, e);
    }
  }

createNameNode方法部分

  public static NameNode createNameNode(String argv[], Configuration conf)
      throws IOException {
    LOG.info("createNameNode " + Arrays.asList(argv));
    if (conf == null)
      conf = new HdfsConfiguration();
    //解析参数
    StartupOption startOpt = parseArguments(argv);
    if (startOpt == null) {
      printUsage(System.err);
      return null;
    }
    //将启动参数加入到配置中
    setStartupOption(conf, startOpt);
    //根据参数不同启动(或执行不同的方法)实例
    switch (startOpt) {
    //格式化HDFS文件系统,格式化完成后退出
      case FORMAT: {
        boolean aborted = format(conf, startOpt.getForceFormat(),
            startOpt.getInteractiveFormat());
        terminate(aborted ? 1 : 0);
        return null; // avoid javac warning
      }
      //生成一个集群ID对集群无影响
      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
      }
      //同步active的镜像,完成后退出
      case BOOTSTRAPSTANDBY: {
        String toolArgs[] = Arrays.copyOfRange(argv, 1, argv.length);
        int rc = BootstrapStandby.run(toolArgs, conf);
        terminate(rc);
        return null; // avoid warning
      }
      //初始化共享的edits 完成后退出
      case INITIALIZESHAREDEDITS: {
        boolean aborted = initializeSharedEdits(conf,
            startOpt.getForceFormat(),
            startOpt.getInteractiveFormat());
        terminate(aborted ? 1 : 0);
        return null; // avoid warning
      }
      //以BACKUP或者 CHECKPOINT的方式启动
      //这里的BackUpNode是NameNode的子类
      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;
      }
      //正常启动NameNode
      default: {
        DefaultMetricsSystem.initialize("NameNode");
        return new NameNode(conf);
      }
    }
  }

OK由于篇幅问题这一篇就到这里吧!

下一篇预报

下一篇将介绍NameNode正常启动的过程,关于NameNode的其它命令部分的代码将在后面的
文章中专门的介绍。

说明文章的主线将以NameNode的启动,和DataNode的通信,以及Block的管理和DataNode的
管理展开,当主线了解完后再回头展开介绍一些细节的代码。


以上内容部分参考了网络上的内容,欢迎大家指正讨论
-联系方式:zhaizhisheng@sina.com


-每天进步一点点
-每天快乐一点点
-每天幸福一点点

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值