Hadoop源码分析六启动文件namenode原理详解
作者:huserblog 发布时间:2021-08-20 01:03:55
1、 namenode启动
在本系列文章三中分析了hadoop的启动文件,其中提到了namenode启动的时候调用的类为
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.error("Failed to start namenode.", e);
terminate(1, e);
}
}
这段代码的重点在第8行,这里createNameNode方法创建了一个namenode对象,然后调用其join方法阻塞等待请求。
createNameNode方法的内容如下:
public static NameNode createNameNode(String argv[], Configuration conf)
throws IOException {
LOG.info("createNameNode " + Arrays.asList(argv));
if (conf == null)
conf = new HdfsConfiguration();
// Parse out some generic args into Configuration.
GenericOptionsParser hParser = new GenericOptionsParser(conf, argv);
argv = hParser.getRemainingArgs();
// Parse the rest, NN specific args.
StartupOption startOpt = parseArguments(argv);
if (startOpt == null) {
printUsage(System.err);
return null;
}
setStartupOption(conf, startOpt);
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);
}
}
}
这段代码很简单。主要做的操作有三个:
1、 创建配置文件对象
2、 解析命令行的参数
3、 根据参数执行对应方法(switch块)
其中创建的配置文件的为HdfsConfiguration(第5行),这里的HdfsConfiguration继承于Configuration类,它会加载hadoop的配置文件到内存中。然后解析传入main方法的参数,根据这个参数执行具体的方法。正常启动的时候执行的default里的内容。default的内容也很简单,就是创建一个Namenode对象。
这里先从HdfsConfiguration开始分析,详细讲解hdfs的配置文件处理。
首先看HdfsConfiguration的初始化方法如下:
public HdfsConfiguration() {
super();
}
这里是调用其父类的初始化方法。
其父类为Configuration类,它的初始化方法如下:
/** A new configuration. */
public Configuration() {
this(true);
}
这里可以看见他是调用了一个重载方法,传入了一个参数:true。
接着细看这个重载方法:
public Configuration(boolean loadDefaults) {
this.loadDefaults = loadDefaults;
updatingResource = new ConcurrentHashMap<String, String[]>();
synchronized(Configuration.class) {
REGISTRY.put(this, null);
}
}
这里也很简单,这里主要是为两个参数赋值,并将新创建的Configuration添加到REGISTRY中。
至此便创建好了一个配置文件。但是关于配置文件的初始化解析还未完成。在java里可以使用static关键字声明一段代码块,这段代码块在类加载的时候会被执行。在Configuration和HdfsConfiguration中都有静态代码块。
首先在Configuration类中,在第682行有一段静态代码块,其内容如下:
这段代码的重点在第695行和第696行,这里调用了一个addDefaultResource方法,这里传入了两个参数core-default.xml和core-site.xml。其中core-site.xml就是在安装hadoop的时候设置的配置文件。而core-default.xml是hadoop自带的配置文件,这个文件可以在hadoop的官方文档里查到,文档链接如下:https://hadoop.apache.org/docs/r2.7.6/hadoop-project-dist/hadoop-common/core-default.xml
同样在hadoop的源码里也有这个文件,它在hadoop-common-XX.jar中。
接着继续分析调用的addDefaultResource方法
其内容如下:
public static synchronized void addDefaultResource(String name) {
if(!defaultResources.contains(name)) {
defaultResources.add(name);
for(Configuration conf : REGISTRY.keySet()) {
if(conf.loadDefaults) {
conf.reloadConfiguration();
}
}
}
}
这段代码也很简单。首先是第二行先从defaultResources中判断是否已经存在该配置文件,
这里的defaultResources是一个list
其定义如下:
private static final CopyOnWriteArrayList<String> defaultResources =
new CopyOnWriteArrayList<String>();
若defaultResources中不存在这个配置文件,则继续向下执行,将这个配置文件添加到defaultResources中(第3行)。然后遍历REGISTRY中的key(第4行),这里的key就是在上文提到的Configuration对象。然后根据其loadDefaults的值来判断是否执行reloadConfiguration方法。
这里的loadDefaults的值就是上文分析的传入重载方法的值,上文传入的为true,所以其创建的Configuration对象在这里会执行reloadConfiguration方法。
reloadConfiguration方法内容如下:
public synchronized void reloadConfiguration() {
properties = null; // trigger reload
finalParameters.clear(); // clear site-limits
}
这里可以看见这个reloadConfiguration方法并没有真正的重新加载配置文件而是将properties的值设置为空。
同样在HdfsConfiguration也有类似的静态代码块,在第30行,其内容如下:
这里首先调用了一个addDeprecatedKeys方法然后调用了一个addDefaultResource。这里的addDefaultResource传了两个文件hdfs-default.xml和hdfs-site.xml。其中hdfs-site.xml是安装时的配置文件,hdfs-default.xml是其自带的默认文件,同上文的core-default.xml一样。官网链接为:https://hadoop.apache.org/docs/r2.7.6/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml。文件位于:hadoop-hdfs-2.7.6.jar。
其中addDeprecatedKeys方法内容如下:
private static void addDeprecatedKeys() {
Configuration.addDeprecations(new DeprecationDelta[] {
new DeprecationDelta("dfs.backup.address",
DFSConfigKeys.DFS_NAMENODE_BACKUP_ADDRESS_KEY),
new DeprecationDelta("dfs.backup.http.address",
DFSConfigKeys.DFS_NAMENODE_BACKUP_HTTP_ADDRESS_KEY),
new DeprecationDelta("dfs.balance.bandwidthPerSec",
DFSConfigKeys.DFS_DATANODE_BALANCE_BANDWIDTHPERSEC_KEY),
new DeprecationDelta("dfs.data.dir",
DFSConfigKeys.DFS_DATANODE_DATA_DIR_KEY),
new DeprecationDelta("dfs.http.address",
DFSConfigKeys.DFS_NAMENODE_HTTP_ADDRESS_KEY),
new DeprecationDelta("dfs.https.address",
DFSConfigKeys.DFS_NAMENODE_HTTPS_ADDRESS_KEY),
new DeprecationDelta("dfs.max.objects",
DFSConfigKeys.DFS_NAMENODE_MAX_OBJECTS_KEY),
new DeprecationDelta("dfs.name.dir",
DFSConfigKeys.DFS_NAMENODE_NAME_DIR_KEY),
new DeprecationDelta("dfs.name.dir.restore",
DFSConfigKeys.DFS_NAMENODE_NAME_DIR_RESTORE_KEY),
new DeprecationDelta("dfs.name.edits.dir",
DFSConfigKeys.DFS_NAMENODE_EDITS_DIR_KEY),
new DeprecationDelta("dfs.read.prefetch.size",
DFSConfigKeys.DFS_CLIENT_READ_PREFETCH_SIZE_KEY),
new DeprecationDelta("dfs.safemode.extension",
DFSConfigKeys.DFS_NAMENODE_SAFEMODE_EXTENSION_KEY),
new DeprecationDelta("dfs.safemode.threshold.pct",
DFSConfigKeys.DFS_NAMENODE_SAFEMODE_THRESHOLD_PCT_KEY),
new DeprecationDelta("dfs.secondary.http.address",
DFSConfigKeys.DFS_NAMENODE_SECONDARY_HTTP_ADDRESS_KEY),
new DeprecationDelta("dfs.socket.timeout",
DFSConfigKeys.DFS_CLIENT_SOCKET_TIMEOUT_KEY),
new DeprecationDelta("fs.checkpoint.dir",
DFSConfigKeys.DFS_NAMENODE_CHECKPOINT_DIR_KEY),
new DeprecationDelta("fs.checkpoint.edits.dir",
DFSConfigKeys.DFS_NAMENODE_CHECKPOINT_EDITS_DIR_KEY),
new DeprecationDelta("fs.checkpoint.period",
DFSConfigKeys.DFS_NAMENODE_CHECKPOINT_PERIOD_KEY),
new DeprecationDelta("heartbeat.recheck.interval",
DFSConfigKeys.DFS_NAMENODE_HEARTBEAT_RECHECK_INTERVAL_KEY),
new DeprecationDelta("dfs.https.client.keystore.resource",
DFSConfigKeys.DFS_CLIENT_HTTPS_KEYSTORE_RESOURCE_KEY),
new DeprecationDelta("dfs.https.need.client.auth",
DFSConfigKeys.DFS_CLIENT_HTTPS_NEED_AUTH_KEY),
new DeprecationDelta("slave.host.name",
DFSConfigKeys.DFS_DATANODE_HOST_NAME_KEY),
new DeprecationDelta("session.id",
DFSConfigKeys.DFS_METRICS_SESSION_ID_KEY),
new DeprecationDelta("dfs.access.time.precision",
DFSConfigKeys.DFS_NAMENODE_ACCESSTIME_PRECISION_KEY),
new DeprecationDelta("dfs.replication.considerLoad",
DFSConfigKeys.DFS_NAMENODE_REPLICATION_CONSIDERLOAD_KEY),
new DeprecationDelta("dfs.replication.interval",
DFSConfigKeys.DFS_NAMENODE_REPLICATION_INTERVAL_KEY),
new DeprecationDelta("dfs.replication.min",
DFSConfigKeys.DFS_NAMENODE_REPLICATION_MIN_KEY),
new DeprecationDelta("dfs.replication.pending.timeout.sec",
DFSConfigKeys.DFS_NAMENODE_REPLICATION_PENDING_TIMEOUT_SEC_KEY),
new DeprecationDelta("dfs.max-repl-streams",
DFSConfigKeys.DFS_NAMENODE_REPLICATION_MAX_STREAMS_KEY),
new DeprecationDelta("dfs.permissions",
DFSConfigKeys.DFS_PERMISSIONS_ENABLED_KEY),
new DeprecationDelta("dfs.permissions.supergroup",
DFSConfigKeys.DFS_PERMISSIONS_SUPERUSERGROUP_KEY),
new DeprecationDelta("dfs.write.packet.size",
DFSConfigKeys.DFS_CLIENT_WRITE_PACKET_SIZE_KEY),
new DeprecationDelta("dfs.block.size",
DFSConfigKeys.DFS_BLOCK_SIZE_KEY),
new DeprecationDelta("dfs.datanode.max.xcievers",
DFSConfigKeys.DFS_DATANODE_MAX_RECEIVER_THREADS_KEY),
new DeprecationDelta("io.bytes.per.checksum",
DFSConfigKeys.DFS_BYTES_PER_CHECKSUM_KEY),
new DeprecationDelta("dfs.federation.nameservices",
DFSConfigKeys.DFS_NAMESERVICES),
new DeprecationDelta("dfs.federation.nameservice.id",
DFSConfigKeys.DFS_NAMESERVICE_ID),
new DeprecationDelta("dfs.client.file-block-storage-locations.timeout",
DFSConfigKeys.DFS_CLIENT_FILE_BLOCK_STORAGE_LOCATIONS_TIMEOUT_MS),
});
}
这段代码很简单,只有一句话。调用了 Configuration的静态方法addDeprecations,并向其中传入了一个参数,参数类型为DeprecationDelta类的数组,并为数组中的数据进行赋值。
以上就是关于Hadoop源码分析启动文件namenode原理详解的详细内容,更多关于Hadoop源码分析的资料请持续关注脚本之家其它相关文章!
来源:https://blog.csdn.net/qq_39210987/article/details/113922325


猜你喜欢
- ButterKnife 算是一款知名老牌 Android 开发框架了,通过注解绑定视图,避免了 findViewById() 的操作,广受好
- C++ 11中的互斥量,声明在 <mutex> 头文件中,互斥量的使用可以在各种方面,比较常用在对共享数据的
- 背景我在准备使用 JVM 的命令时候观察程序的动态,但是发现 Main 函数启动就退出了,所以也没办法直接观察,于是想到了如何让 Main
- OkHttp(GitHub:https://github.com/square/okhttp) 的 Interceptor 就如同名称「拦截
- 在Android中要让一个程序的界面始终保持一个方向,不随手机方向转动而变化的办法: 只要在AndroidManifest.xml里面配置一
- 访问控制:private 私有的protected 受保护的public 公共的类、方法和变量修饰符abstract 声明抽象class 类
- 一、引言想实现一个空白的画板,上面可以画出手滑动的轨迹,就这么一个小需求。一般就来讲就两种实现方式,view或者surfaceview。下面
- 核心代码: File fatherFile = new File(path);File[] files = fatherFile.listF
- 1,Java中操作方法:import java.io.*; public class FileInputStreamTest &
- 1 前言任何一门语言都需要基本的流程控制语句,其思想也符合人类判断问题或做事的逻辑过程。什么是流程控制呢?流程就是做一件事情的顺序,或者说是
- 一、概述现在app中,图片预览功能肯定是少不了的,用户基本已经形成条件反射,看到小图,点击看大图,看到大图两个手指开始进行放大,放大后,开始
- java7增强的try语句关闭资源传统的关闭资源方式import java.io.FileInputStream;import java.i
- 本文实例为大家分享了java微信公众号支付示例代码,供大家参考,具体内容如下开始之前,先准备好:appid、商家号、商户密匙。工具类:MD5
- 一、根据流向分为输入流和输出流:注意输入流和输出流是相对于程序而言的。输出:把程序(内存)中的内容输出到磁盘、光盘等存储设备中输入:读取外部
- 持久化类Hibernate的整个概念是采取从Java类属性的值,并将持久到数据库表。一个映射文件Hibernate的帮助确定如何从拉动类的值
- http请求绕过Filter的实现实例场景:两个web服务器,A当做服务端,B为客户端,B通过Hessian远程访问A。A上加了sessio
- 前言出去面试的时候,对java的集合框架考察的知识点还是蛮多的。除了基础的集合常见API使用,对集合底层的实现原理以及数据结构等也有很多考察
- 一、数组(Array)数组具有以下的特点:数组属于线性结构,在内存中是连续存放的。数组的元素类型必须相同。数组可以直接通过下标访问。数组的查
- spring Boot 熟悉后,集成一个外部扩展是一件很容易的事,集成Redis也很简单,看下面步骤配置:一、添加pom依赖
- java中的线程状态🥇在操作系统层面,一个线程就两个状态:就绪和阻塞状态.但是java中为了在线程阻塞时能够更快速的知晓一个线程阻塞的原因,