body { margin: 0 auto; font: 13px / 1 Helvetica, Arial, sans-serif; color: rgba(68, 68, 68, 1); padding: 5px }
h1, h2, h3, h4 { color: rgba(17, 17, 17, 1); font-weight: 400 }
h1, h2, h3, h4, h5, p { margin-bottom: 16px; padding: 0 }
h1 { font-size: 28px }
h2 { font-size: 22px; margin: 20px 0 6px }
h3 { font-size: 21px }
h4 { font-size: 18px }
h5 { font-size: 16px }
a { color: rgba(0, 153, 255, 1); margin: 0; padding: 0; vertical-align: baseline }
a:link, a:visited { text-decoration: none }
a:hover { text-decoration: underline }
ul, ol { padding: 0; margin: 0 }
li { line-height: 24px; margin-left: 30px }
li ul, li ul { margin-left: 24px }
ul, ol { font-size: 14px; line-height: 20px; max-width: 98% }
p { font-size: 14px; line-height: 20px; max-width: 98%; margin-top: 3px }
pre { padding: 0 4px; max-width: 98%; white-space: pre; word-wrap: normal; overflow: auto; font-family: Consolas, Monaco, Andale Mono, monospace; line-height: 1.5; font-size: 13px; border: 1px solid rgba(221, 221, 221, 1); background-color: rgba(247, 247, 247, 1); border-radius: 3px }
code { font-family: Consolas, Monaco, Andale Mono, monospace; line-height: 1.5; font-size: 13px; border: 1px solid rgba(221, 221, 221, 1); background-color: rgba(247, 247, 247, 1); border-radius: 3px }
code pref { color: rgba(255, 0, 0, 1) }
pre code { border: 0 }
aside { display: block; float: right; width: 390px }
blockquote { border-left: 0.5em solid rgba(64, 170, 83, 1); padding: 0 2em; margin-left: 0; max-width: 98% }
blockquote cite { font-size: 14px; line-height: 20px; color: rgba(191, 191, 191, 1) }
blockquote cite:before { content: "— " }
blockquote p { color: rgba(102, 102, 102, 1); max-width: 98% }
hr { height: 1px; border-top: 1px dashed rgba(0, 102, 204, 1); border-right: none; border-bottom: none; border-left: none }
button, input, select, textarea { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle }
button, input { line-height: normal; *overflow: visible }
{ border: 0; padding: 0 }
button, input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button }
input[type="checkbox"], input[type="radio"] { cursor: pointer }
input:not([type="image"]), textarea { -webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box }
input[type="search"] { -webkit-appearance: textfield; -webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box }
{ -webkit-appearance: none }
label, input, select, textarea { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 13px; font-weight: normal; line-height: normal; margin-bottom: 18px }
input[type="checkbox"], input[type="radio"] { cursor: pointer; margin-bottom: 0 }
input[type="text"], input[type="password"], textarea, select { display: inline-block; width: 210px; padding: 4px; font-size: 13px; font-weight: normal; line-height: 18px; height: 18px; color: rgba(128, 128, 128, 1); border: 1px solid rgba(204, 204, 204, 1); -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px }
select, input[type="file"] { height: 27px; line-height: 27px }
textarea { height: auto }
{ color: rgba(191, 191, 191, 1) }
{ color: rgba(191, 191, 191, 1) }
input[type="text"], input[type="password"], select, textarea { -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; -moz-transition: border linear 0.2s, box-shadow linear 0.2s; transition: border 0.2s linear, box-shadow 0.2s linear; -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1) }
input[type="text"]:focus, input[type="password"]:focus, textarea:focus { outline: none; border-color: rgba(82, 168, 236, 0.8); -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6) }
button { display: inline-block; padding: 4px 14px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 13px; line-height: 18px; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 1px rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); background-color: rgba(0, 100, 205, 1); background-repeat: repeat-x; color: rgba(255, 255, 255, 1); text-shadow: 0 -1px rgba(0, 0, 0, 0.25); border-top: 1px solid rgba(0, 0, 0, 0.1); border-right: 1px solid rgba(0, 0, 0, 0.1); border-bottom: 1px solid rgba(0, 0, 0, 0.25); border-left: 1px solid rgba(0, 0, 0, 0.1); -webkit-transition: 0.1s linear all; -moz-transition: 0.1s linear all; transition: all 0.1s linear }
button:hover { color: rgba(255, 255, 255, 1); background-position: 0 -15px; text-decoration: none }
button:active { -webkit-box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05) }
{ padding: 0; border: 0 }
table { border-spacing: 0; border: 1px solid rgba(204, 204, 204, 1) }
td, th { border: 1px solid rgba(204, 204, 204, 1); padding: 5px }
pre .literal, pre .comment, pre .template_comment, pre .diff .header, pre .javadoc { color: rgba(0, 128, 0, 1) }
pre .keyword, pre .css .rule .keyword, pre .winutils, pre .javascript .title, pre .nginx .title, pre .subst, pre .request, pre .status { color: rgba(0, 0, 255, 1); font-weight: bold }
pre .number, pre .hexcolor, pre .python .decorator, pre .ruby .constant { color: rgba(0, 0, 255, 1) }
pre .string, pre .tag .value, pre .phpdoc, pre .tex .formula { color: rgba(221, 17, 68, 1) }
pre .title, pre .id { color: rgba(153, 0, 0, 1); font-weight: bold }
pre .javascript .title, pre .lisp .title, pre .clojure .title, pre .subst { font-weight: normal }
pre .class .title, pre .haskell .type, pre .vhdl .literal, pre .tex .command { color: rgba(68, 85, 136, 1); font-weight: bold }
pre .tag, pre .tag .title, pre .rules .property, pre .django .tag .keyword { color: rgba(0, 0, 128, 1); font-weight: normal }
pre .attribute, pre .variable, pre .lisp .body { color: rgba(0, 128, 128, 1) }
pre .regexp { color: rgba(0, 153, 38, 1) }
pre .class { color: rgba(68, 85, 136, 1); font-weight: bold }
pre .symbol, pre .ruby .symbol .string, pre .lisp .keyword, pre .tex .special, pre .prompt { color: rgba(153, 0, 115, 1) }
pre .built_in, pre .lisp .title, pre .clojure .built_in { color: rgba(0, 134, 179, 1) }
pre .preprocessor, pre .pi, pre .doctype, pre .shebang, pre .cdata { color: rgba(153, 153, 153, 1); font-weight: bold }
pre .deletion { background: rgba(255, 221, 221, 1) }
pre .addition { background: rgba(221, 255, 221, 1) }
pre .diff .change { background: rgba(0, 134, 179, 1) }
pre .chunk { color: rgba(170, 170, 170, 1) }
pre .markdown .header { color: rgba(136, 0, 0, 1); font-weight: bold }
pre .markdown .blockquote { color: rgba(136, 136, 136, 1) }
pre .markdown .link_label { color: rgba(136, 136, 255, 1) }
pre .markdown .strong { font-weight: bold }
pre .markdown .emphasis { font-style: italic }
pref { color: rgba(255, 0, 0, 1) }

基于源码源码分析hadoop namenode格式化和启动过程实现 (According to the source code analysis hadoop namenode formatting and startup process implementation.)

Namenode 管理hdfs元数据和RPC服务响应客户端,初次使用时需格式化;元数据存储在edits和fsimage文件,其中 fsimage 保存最新的元数据信息,edits 保存自最新的元数据信息后的变化;edits 存储的信息会在下一次启动 namenode 时与 fsimage 合并产生新的 fsimage 文件。我们先以1.0版本源码为例介绍,后期再补充新版本的扩展和改变,由于篇幅原因,部分代码被去除。

1 namenode 格式化

初次启动namenode时,hadoop要求必须格式化namenode;

hadoop namenode -format

格式化会删除namenode image和edits文件,再创建新的 image 和 edits;

public static void format(File dir, Configuration conf)
throws IOException {
File image = new File(dir, "image");
File edits = new File(dir, "edits"); if (!((!image.exists() || FileUtil.fullyDelete(image, conf)) &&
(!edits.exists() || edits.delete()) &&image.mkdirs())) { throw new IOException("Unable to format: "+dir);
}
}

所以已经生产使用的集群,谨慎使用。

2 namenode初始化和启动

Configuration conf = new Configuration();
NameNode namenode = new NameNode(conf);
namenode.join();

namenode初始化和启动过程中四个重要的操作: 1. 根据(fs.default.name(旧版本参数)/fs.defaultFS(新版本参数))配置的主机名和端口号创建套接字地址,这个地址就是 namenode 文件系统元数据地址; 2. 加载 namenode 元数据;首先将现有的 image 数据以层级方式加载到内存列表,加载完成后存放到活动列表中;

TreeSet activeBlocks = new TreeSet();
DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(curFile)));
try {
int numFiles = in.readInt();
for (int i = 0; i < numFiles; i++) {
UTF8 name = new UTF8();
name.readFields(in);
int numBlocks = in.readInt();
if (numBlocks == 0) {
unprotectedAddFile(name, null);
} else {
Block blocks[] = new Block[numBlocks];
for (int j = 0; j < numBlocks; j++) {
blocks[j] = new Block();
blocks[j].readFields(in);
}
unprotectedAddFile(name, blocks);
}
}
} finally {
in.close();
}

对于存储了大量数据的集群,元数据加载到内存会比较耗时,总的元数据数 / 加载完成后存放到活动列表 的数量 * 100% 就是我们在前端界面看到的namenode启动进度。image 加载完成后,继续加载最新的 edits ,并将 edits 合并到 image 产生新的 image 文件,并创建一个新的 edits 文件记录系统运行时的变化。

public FSDirectory(File dir) throws IOException {
File fullimage = new File(dir, "image");
if (! fullimage.exists()) {
throw new IOException("NameNode not formatted: " + dir);
}
File edits = new File(dir, "edits");
if (loadFSImage(fullimage, edits)) {
saveFSImage(fullimage, edits);
} synchronized (this) {
this.ready = true;
this.notifyAll();
this.editlog = new DataOutputStream(new FileOutputStream(edits));
}
}
  1. 创建datanode节点和namenode心跳监控、创建租凭管理监控(可以理解为锁管理,比如释放锁);

    this.hbthread = new Daemon(new HeartbeatMonitor());
    this.lmthread = new Daemon(new LeaseMonitor());
    hbthread.start();
    lmthread.start();

    namenode通过间隔的检查与datanode心跳来判断datanode的存活;租凭管理监控通俗的理解就是当某个操作(比如:写数据)超出namenode规定的最大操作时间时,这个租凭管理监控进程就会认为该操作过期了,将它释放清除。

    while ((sortedLeases.size() > 0) &&((top = (Lease) sortedLeases.first()) != null)) {
    if (top.expired()) {
    top.releaseLocks();
    leases.remove(top.holder);
    LOG.info("Removing lease " + top + ", leases remaining: " + sortedLeases.size());
    if (!sortedLeases.remove(top)) {
    LOG.info("Unknown failure trying to remove " + top + " from lease set.");
    }
    } else {
    break;
    }
    }
  2. 为namenode创建RPC服务器(线程池),这个线程池的作用是用来处理客户端的远程过程调用及集群守护进程的调用

    public NameNode(Configuration conf) throws IOException {
    this(getDir(conf),DataNode.createSocketAddr(conf.get("fs.default.name", "local")).getPort(), conf);
    }

public NameNode(File dir, int port, Configuration conf) throws IOException { this.namesystem = new FSNamesystem(dir, conf); this.handlerCount = conf.getInt("dfs.namenode.handler.count", 10); this.server = RPC.getServer(this, port, handlerCount, false, conf); this.server.start(); }

通过dfs.namenode.handler.count 参数设置线程池大小,默认是10;
```xml
public synchronized void start() throws IOException {
Listener listener = new Listener();
listener.start(); for (int i = 0; i < handlerCount; i++) {
Handler handler = new Handler(i);
handler.start();
}
}

在生产环境中,该参数的设置需要多方面考虑和商榷,对于大集群,来自不同DataNode的并发心跳以及客户端并发的元数据操作可能巨大,如果线程池太小,总是忙碌状态,客户端连接NameNode的时候总是超时或者连接被拒绝,这意味着需要更大的池来处理;线程池太大,会引发调用延迟和增加主机负载等问题;

this.server = RPC.getServer(this, port, handlerCount, false, conf);
this.server.start();

到此RPC服务器(线程池)构建并启动,整个namenode启动完成,RPC服务器(线程池)进入监听响应状态;

210116 222524 Server listener on port 9000: starting
210116 222524 Server handler 0 on 9000: starting
210116 222524 Server handler 1 on 9000: starting
210116 222524 Server handler 2 on 9000: starting
210116 222524 Server handler 3 on 9000: starting
210116 222524 Server handler 4 on 9000: starting
210116 222524 Server handler 5 on 9000: starting
210116 222524 Server handler 6 on 9000: starting
210116 222524 Server handler 7 on 9000: starting
210116 222524 Server handler 8 on 9000: starting
210116 222524 Server handler 9 on 9000: starting

3 总结

Namenode 格式化就是删除已经存在的edits和fsimage文件,创建新的;Namenode启动时创建套接字地址、加载 namenode 元数据、创建监控进程(datanode节点和namenode心跳监控、租凭管理监控)、创建RPC服务器(线程池)。

参考文献

Hadoop源码:namenode格式化和启动过程实现的更多相关文章

  1. Netty源码分析之客户端启动过程

    一.先来看一下客户端示例代码. public class NettyClientTest { public void connect(int port, String host) throws Exc ...

  2. tomcat8 源码分析 | 组件及启动过程

    tomcat 8 源码分析 ,本文主要讲解tomcat拥有哪些组件,容器,又是如何启动的 推荐访问我的个人网站,排版更好看呦: https://chenmingyu.top/tomcat-source ...

  3. Fabric1.4源码解析: 链码容器启动过程

    想写点东西记录一下最近看的一些Fabric源码,本文使用的是fabric1.4的版本,所以对于其他版本的fabric,内容可能会有所不同. 本文想针对Fabric中链码容器的启动过程进行源码的解析.这 ...

  4. Spring源码系列——容器的启动过程(一)

    一. 前言 Spring家族特别庞大,对于开发人员而言,要想全面征服Spring家族,得花费不少的力气.俗话说,打蛇打七寸,那么Spring家族的"七寸"是什么呢?我心目中的答案一 ...

  5. Netty源码解析 -- 服务端启动过程

    本文通过阅读Netty源码,解析Netty服务端启动过程. 源码分析基于Netty 4.1 Netty是一个高性能的网络通信框架,支持NIO,OIO等多种IO模式.通常,我们都是使用NIO模式,该系列 ...

  6. Android源码——Activity组件的启动过程

    根Activity启动过程 Launcher启动MainActivity的过程主要分为6个步骤: 一.Launcher向ActivityManagerService发送一个启动MainActivity ...

  7. Spring源码解析-Web容器启动过程

    Web容器启动过程,主要讲解Servlet和Spring容器结合的内容. 流程图如下: Web容器启动的Root Context是有ContextLoaderListener,一般使用spring,都 ...

  8. wxWidgets源码分析(1) - App启动过程

    目录 APP启动过程 wxApp入口定义 wxApp实例化准备 wxApp的实例化 wxApp运行 总结 APP启动过程 本文主要介绍wxWidgets应用程序的启动过程,从app.cpp入手. wx ...

  9. Hive源码分析(1)——HiveServer2启动过程

    1.想了解HiveServer2的启动过程,则需要找到启动HiveServer2的入口,hive服务的启动命令为hive --service HiveServer2,通过分析$HIVE_HOME/bi ...

随机推荐

  1. Anno 让微服务、混合编程更简单(Net love Java)

    在社区或者QQ群我们经常看到有人争辩编程语言的好坏,只要一提起这个话题常常就能引来很多人参与,往往最后就变成了一群人几个小时的骂战.今天我们要说的是如何让Java和.Net(甚至更多语言)相结合.充分 ...

  2. SpringBoot + Layui + JustAuth +Mybatis-plus实现可第三方登录的简单后台管理系统

    1. 简介   在之前博客:SpringBoot基于JustAuth实现第三方授权登录 和 SpringBoot + Layui +Mybatis-plus实现简单后台管理系统(内置安全过滤器)上改造 ...

  3. Flink读写Redis(二)-flink-redis-connector代码学习

    源码结构 RedisSink package org.apache.flink.streaming.connectors.redis; import org.apache.flink.configur ...

  4. pag object设模式

    pag object 是自动化测试最佳模式测试之一,它主要体现在对界面交互细节的封装 优点: 减少代码重复,提高测试的可读性,提搞测试用例的可维护性.

  5. 是的,你没看错!Python可以实现自动化办公

    是的,你没看错!Python可以实现自动化办公 公众号[伤心的辣条],如今越来越多的人加入到学习Python的队伍当中,尤其是对于很多职场人来说,不管你是程序员还是非程序员,Python已经为很多职场 ...

  6. 个人微信公众号搭建Python实现 -个人公众号搭建-运行run方法的编写(14.3.3)

    @ 目录 1.主要逻辑 2.代码 关于作者 1.主要逻辑 使用的是flask服务器 就使用一个函数处理请求 第一个是验证服务器,返回微信服务器给的字符串就表示验证成功 第二是要处理微信服务器发送过来的 ...

  7. JavaScript实现自定义右键菜单

    JavaScript实现自定义右键菜单,思路如下: 1. 屏蔽默认右键事件: 2. 隐藏自定义的菜单模块(如div.ul等): 3. 右键点击特定或非特定区域,显示菜单模块: 4. 再次点击,隐藏菜单 ...

  8. xxfpmW 的诞生过程

    最近因为在win 服务器搭建php服务,发现php-cgi.exe 很容易崩溃,看cpu和硬盘都没有暴涨,也不知道啥原因,网上查发现有一款xxfpm 小应用可以解决这个问题,但这个应用是2011年开发 ...

  9. Keras使用多个GPU并行

    model = Model(inputs=[v_i, v_j], outputs=output_list) model = multi_gpu_model(model,4) model.compile ...

  10. JavaScript获取页面元素方法