共计 7836 个字符,预计需要花费 20 分钟才能阅读完成。
在 Hadoop-2.X 中,使用 hdfs namenode –format 对文件系统进行格式化。虽然无论是在生产环境还是测试环境中,已经使用了该命令若干次了,也大体了解该命令就是在本地文件系统中创建几个文件夹,但具体是如何执行的则需要通过阅读源代码来了解了。
要想看到该命令的源代码,需要看看 hdfs 脚本中是如何执行相应的 java 类的。在 hdfs 脚本中,下面的语句说明了实际执行的 java 类和参数,其中类为 org.apache.hadoop.hdfs.server.namenode.NameNode,参数为 -format。虽然在命令行中输入的为 hdfs namenode –forma,但将 namenode 赋予了 COMMAND,并进行了参数的移位,这样参数就剩下了 -format。
————————————– 分割线 ————————————–
Ubuntu 13.04 上搭建 Hadoop 环境 http://www.linuxidc.com/Linux/2013-06/86106.htm
Ubuntu 12.10 +Hadoop 1.2.1 版本集群配置 http://www.linuxidc.com/Linux/2013-09/90600.htm
Ubuntu 上搭建 Hadoop 环境(单机模式 + 伪分布模式)http://www.linuxidc.com/Linux/2013-01/77681.htm
Ubuntu 下 Hadoop 环境的配置 http://www.linuxidc.com/Linux/2012-11/74539.htm
单机版搭建 Hadoop 环境图文教程详解 http://www.linuxidc.com/Linux/2012-02/53927.htm
搭建 Hadoop 环境(在 Winodws 环境下用虚拟机虚拟两个 Ubuntu 系统进行搭建)http://www.linuxidc.com/Linux/2011-12/48894.htm
————————————– 分割线 ————————————–
COMMAND=$1
Shift
if [“$COMMAND” = “namenode”] ; then
CLASS=’org.apache.hadoop.hdfs.server.namenode.NameNode’
HADOOP_OPTS=”$HADOOP_OPTS $HADOOP_NAMENODE_OPTS”
exec “$JAVA” -Dproc_$COMMAND $JAVA_HEAP_MAX $HADOOP_OPTS $CLASS “$@”
在 eclipse 中找到 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);
}
}
其中 parseHelpArgument 方法用于解析命令行参数,startupShutdownMessage 方法输出启动和关闭的信息,NameNode 的主要工作由 createNameNode 方法完成。在 createNameNode 中执行 format 方法之前先对参数进行了解析,具体代码如下,其中 argv 根据 format 时使用的参数可以为:-format [-clusterid cid] [-force] [-nonInteractive](完整的命令为 hdfs namenode [-format [-clusterid cid] [-force] [-nonInteractive]])。该方法用于设置 StartupOption 中的 clusterId 为 cid,若使用了 -force 参数则 StartupOption 中的 isForceFormat 为 true,若使用了 -nonInteractive 则将 StartupOption 中的 isInteractiveFormat 为 false,后两个参数的默认值为 false 和 true。
StartupOption startOpt = parseArguments(argv);
在 createNameNode 方法中与 -format 有关系的代码如下,且在执行完毕后返回 null,结合 main 方法中的代码可以得知,HDFS 的 format 执行完毕。format 方法的参数分别为 HdfsConfiguration、isForceFormat 和 isInteractiveFormat。
case FORMAT: {
boolean aborted = format(conf, startOpt.getForceFormat(),
startOpt.getInteractiveFormat());
terminate(aborted ? 1 : 0);
return null; // avoid javac warning
}
接下来进入 format 方法,看看具体都执行了哪些操作,由于该方法是整个 HDFS 格式化的核心方法,所以会完整细致的分析该方法,这样势必会将整个方法分成几个部分,下面是第一部分的代码,这部分代码用于获取 NameNode 的 NameServiceID 和 NameNode ID,并检查 NameNode 是否允许格式化,其中使用了参数 dfs.namenode.support.allow.format,该参数的默认值为 true(在生产环境中可以在格式化完成后将该参数设置为 false,避免格式化正在运行的 HDFS)。
String nsId = DFSUtil.getNamenodeNameServiceId(conf);
String namenodeId = HAUtil.getNameNodeId(conf, nsId);
initializeGenericKeys(conf, nsId, namenodeId);
checkAllowFormat(conf);
if (UserGroupInformation.isSecurityEnabled()) {
InetSocketAddress socAddr = getAddress(conf);
SecurityUtil.login(conf, DFS_NAMENODE_KEYTAB_FILE_KEY,
DFS_NAMENODE_USER_NAME_KEY, socAddr.getHostName());
}
更多详情见请继续阅读下一页的精彩内容 :http://www.linuxidc.com/Linux/2014-09/107140p2.htm
第二部分代码如下,主要根据配置文件获取要格式化的目录、存储 edits 日志的目录等,以及在未指定 clusterId 的情况生成新的 clusterId 用于标识命名空间。
/* 获取参数 dfs.namenode.name.dir 设置的目录,该值用于存储 fsimage
* 默认值为 file://${Hadoop.tmp.dir}/dfs/name,
* 其中 hadoop.tmp.dir 定义在 core-default.xml 中,值为 /tmp/hadoop-${user.name}
*/
Collection<URI> nameDirsToFormat = FSNamesystem.getNamespaceDirs(conf);
/* 获取在 primary 和 secondary namenode 之间共享的 edits 目录
* 相应的参数为 dfs.namenode.shared.edits.dir
*/
List<URI> sharedDirs = FSNamesystem.getSharedEditsDirs(conf);
List<URI> dirsToPrompt = new ArrayList<URI>();
dirsToPrompt.addAll(nameDirsToFormat);
dirsToPrompt.addAll(sharedDirs);
/* 获取保存 edits 的目录,对应的参数为 dfs.namenode.edits.dir
* 若上面的参数没有配置,则使用与 fsimage 一致的目录
*/
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 和 edits 文件的工作,由于这两个文件的创建可以做为单独的源码分析进行,在此就不进行详细地分析,会有专门的文章学习这部分代码。
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);
现在已经分析完了执行 hdfs namenode –format 命令时都执行了哪些操作,其实就是根据配置文件中的特定参数如 dfs.namenode.name.dir 等,将 fsimage 和 edits 文件写入这些目录,而 fsimage 和 edits 文件的创建及格式等分析见:http://www.linuxidc.com/Linux/2014-09/107139.htm。
更多 Hadoop 相关信息见 Hadoop 专题页面 http://www.linuxidc.com/topicnews.aspx?tid=13
在 Hadoop-2.X 中,使用 hdfs namenode –format 对文件系统进行格式化。虽然无论是在生产环境还是测试环境中,已经使用了该命令若干次了,也大体了解该命令就是在本地文件系统中创建几个文件夹,但具体是如何执行的则需要通过阅读源代码来了解了。
要想看到该命令的源代码,需要看看 hdfs 脚本中是如何执行相应的 java 类的。在 hdfs 脚本中,下面的语句说明了实际执行的 java 类和参数,其中类为 org.apache.hadoop.hdfs.server.namenode.NameNode,参数为 -format。虽然在命令行中输入的为 hdfs namenode –forma,但将 namenode 赋予了 COMMAND,并进行了参数的移位,这样参数就剩下了 -format。
————————————– 分割线 ————————————–
Ubuntu 13.04 上搭建 Hadoop 环境 http://www.linuxidc.com/Linux/2013-06/86106.htm
Ubuntu 12.10 +Hadoop 1.2.1 版本集群配置 http://www.linuxidc.com/Linux/2013-09/90600.htm
Ubuntu 上搭建 Hadoop 环境(单机模式 + 伪分布模式)http://www.linuxidc.com/Linux/2013-01/77681.htm
Ubuntu 下 Hadoop 环境的配置 http://www.linuxidc.com/Linux/2012-11/74539.htm
单机版搭建 Hadoop 环境图文教程详解 http://www.linuxidc.com/Linux/2012-02/53927.htm
搭建 Hadoop 环境(在 Winodws 环境下用虚拟机虚拟两个 Ubuntu 系统进行搭建)http://www.linuxidc.com/Linux/2011-12/48894.htm
————————————– 分割线 ————————————–
COMMAND=$1
Shift
if [“$COMMAND” = “namenode”] ; then
CLASS=’org.apache.hadoop.hdfs.server.namenode.NameNode’
HADOOP_OPTS=”$HADOOP_OPTS $HADOOP_NAMENODE_OPTS”
exec “$JAVA” -Dproc_$COMMAND $JAVA_HEAP_MAX $HADOOP_OPTS $CLASS “$@”
在 eclipse 中找到 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);
}
}
其中 parseHelpArgument 方法用于解析命令行参数,startupShutdownMessage 方法输出启动和关闭的信息,NameNode 的主要工作由 createNameNode 方法完成。在 createNameNode 中执行 format 方法之前先对参数进行了解析,具体代码如下,其中 argv 根据 format 时使用的参数可以为:-format [-clusterid cid] [-force] [-nonInteractive](完整的命令为 hdfs namenode [-format [-clusterid cid] [-force] [-nonInteractive]])。该方法用于设置 StartupOption 中的 clusterId 为 cid,若使用了 -force 参数则 StartupOption 中的 isForceFormat 为 true,若使用了 -nonInteractive 则将 StartupOption 中的 isInteractiveFormat 为 false,后两个参数的默认值为 false 和 true。
StartupOption startOpt = parseArguments(argv);
在 createNameNode 方法中与 -format 有关系的代码如下,且在执行完毕后返回 null,结合 main 方法中的代码可以得知,HDFS 的 format 执行完毕。format 方法的参数分别为 HdfsConfiguration、isForceFormat 和 isInteractiveFormat。
case FORMAT: {
boolean aborted = format(conf, startOpt.getForceFormat(),
startOpt.getInteractiveFormat());
terminate(aborted ? 1 : 0);
return null; // avoid javac warning
}
接下来进入 format 方法,看看具体都执行了哪些操作,由于该方法是整个 HDFS 格式化的核心方法,所以会完整细致的分析该方法,这样势必会将整个方法分成几个部分,下面是第一部分的代码,这部分代码用于获取 NameNode 的 NameServiceID 和 NameNode ID,并检查 NameNode 是否允许格式化,其中使用了参数 dfs.namenode.support.allow.format,该参数的默认值为 true(在生产环境中可以在格式化完成后将该参数设置为 false,避免格式化正在运行的 HDFS)。
String nsId = DFSUtil.getNamenodeNameServiceId(conf);
String namenodeId = HAUtil.getNameNodeId(conf, nsId);
initializeGenericKeys(conf, nsId, namenodeId);
checkAllowFormat(conf);
if (UserGroupInformation.isSecurityEnabled()) {
InetSocketAddress socAddr = getAddress(conf);
SecurityUtil.login(conf, DFS_NAMENODE_KEYTAB_FILE_KEY,
DFS_NAMENODE_USER_NAME_KEY, socAddr.getHostName());
}
更多详情见请继续阅读下一页的精彩内容 :http://www.linuxidc.com/Linux/2014-09/107140p2.htm