设为首页 收藏本站
查看: 604|回复: 0

[经验分享] hadoop 0.1.0版本namenode代码分析

[复制链接]

尚未签到

发表于 2016-12-12 08:56:39 | 显示全部楼层 |阅读模式
  在对hbase有了一点了解后最近开始学习hadoop的相关源码,首先看了下某高人的hadoop源码分析系列http://caibinbupt.iyunv.com/blog/monthblog/2008-11,看了三十几篇停了,有些看不懂,虽然代码解释的比较细但类实在太多,想一下子理清思路比较难。果断使用学习hbase时的方法,把hadoop最原始的化石版本0.1.0搞来看看,本文将介绍namenode的重要逻辑实现。
  namenode初始化流程:
  1.初始化FSNamespace(处理hadoop中虚拟文件系统的大多逻辑)

2.初始化配置
  FSNamespace初始化

1。初始化FSDirectory

2.初始化HeartbeatMonitor,管理datanode的心跳,超时则删除此节点

3.初始化LeaseMonitor,管理hadoop的契约,会定期处理超时的操作
  

FSDirectory初始化:

1.loadFSImage 从image load 文件名=》blockid的map

2.saveFSImage 把1的map持久化到文件

3.this.editlog = new DataOutputStream 打开editlog的输出流,准备随时写入
  0.1.0版本果然是非常的简单,namenode在启动后啥也不干,只是接受RPC请求,所以后面会以重要函数为切入介绍namenode。
  FSDirectory.LoadFsImage:
  作用:我们知道namenode需要维护filename-》blocksequence的map,LoadFsImage就是从image文件中load 该map

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);
}
}
  解读:
  1.很有意思,image的读写中全是直接的readField和writeField来做持久化,没有任何读写object
  2.numBlocks为零即为目录
  3.Block对象包括blockId,length

synchronized (rootDir) {
if (blocks != null) {
// Add file->block mapping
for (int i = 0; i < blocks.length; i++) {
activeBlocks.add(blocks);
}
}
return (rootDir.addNode(name.toString(), blocks) != null);
}
  执行rootDir.addNode添加该node,包括文件名和对应的blocks。
  解释下INode类:
  类似Linux中INode的概念,看下INode的成员变量

class INode :
public String name;
public INode parent;
public TreeMap children = new TreeMap();
public Block blocks[];

  包含了文件名,父亲节点,孩子节点,和文件实际的blocks
  再来看addNode方法:

INode addNode(String target, Block blks[]) {
if (getNode(target) != null) {
return null;
} else {
String parentName = DFSFile.getDFSParent(target);
if (parentName == null) {
return null;
}
INode parentNode = getNode(parentName);
if (parentNode == null) {
return null;
} else {
String targetName = new File(target).getName();
INode newItem = new INode(targetName, parentNode, blks);
parentNode.children.put(targetName, newItem);
return newItem;
}
}
}
  1.首先尝试getNode,如果取到INode对象表示已经有该节点,返回失败
  2.DFSFile.getDFSParent拿到parent文件夹的名字,方法是简单的字符串操作
  3.拿到parent INode
  4.创新新INode,并添加到parent中。这边调用了 new File().getName,没太明白,应该不会真的创建文件的,只是调用下getName方法。
  再看下getNode方法:

  Vector components = new Vector();
int start = 0;
int slashid = 0;
while (start < target.length() && (slashid = target.indexOf('/', start)) >= 0) {
components.add(target.substring(start, slashid));
start = slashid + 1;
}
if (start < target.length()) {
components.add(target.substring(start));
}
return getNode(components, 0);
  根据'/'符把文件路径分割成一个个component,然后调用getNode(components,0)递归获取INode。

INode getNode(Vector components, int index) {
if (! name.equals((String) components.elementAt(index))) {
return null;
}
if (index == components.size()-1) {
return this;
}
// Check with children
INode child = (INode) children.get(components.elementAt(index+1));
if (child == null) {
return null;
} else {
return child.getNode(components, index+1);
}
}
  这样,通过调用LoadFsImage方法就成功将Image中的数据转换为Inode对象挂到rootNode上了。
  Namenode.open:
  方法申明:public LocatedBlock[] open(String src)
  作用:client从namenode打开一个文件
  LocatedBlock包括了该文件需要的blocks和每个block对应的datanode的集合,在实际读取过程中每个block会随即从拥有该block的datanode中读出block。

public LocatedBlock[] open(String src) throws IOException {
Object openResults[] = namesystem.open(new UTF8(src));
if (openResults == null) {
throw new IOException("Cannot open filename " + src);
} else {
Block blocks[] = (Block[]) openResults[0];
DatanodeInfo sets[][] = (DatanodeInfo[][]) openResults[1];
LocatedBlock results[] = new LocatedBlock[blocks.length];
for (int i = 0; i < blocks.length; i++) {
results = new LocatedBlock(blocks, sets);
}
return results;
}
}
  namesystem.open

public Object[] open(UTF8 src) {
Object results[] = null;
Block blocks[] = dir.getFile(src);
if (blocks != null) {
results = new Object[2];
DatanodeInfo machineSets[][] = new DatanodeInfo[blocks.length][];
for (int i = 0; i < blocks.length; i++) {
TreeSet containingNodes = (TreeSet) blocksMap.get(blocks);
if (containingNodes == null) {
machineSets = new DatanodeInfo[0];
} else {
machineSets = new DatanodeInfo[containingNodes.size()];
int j = 0;
for (Iterator it = containingNodes.iterator(); it.hasNext(); j++) {
machineSets[j] = (DatanodeInfo) it.next();
}
}
}
results[0] = blocks;
results[1] = machineSets;
}
return results;
}
  首先通过dir.getFile拿到该文件对应的blocks列表,然后从block->datanode的map中取出相应的machineSets。
  namenode的主要逻辑我个人感觉搞清楚file->blockseqid和blockid->machineSet这2个map就差不多了。后面有空会分析下最新的hadoop2.0的代码。
  是时候看点真正的代码了!。。。

  


  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-313012-1-1.html 上篇帖子: [Hadoop] 新API容易遇到的一个问题: expected LongWritable recieved Text 下篇帖子: Hadoop迭代式计算开源机器学习框架Shifu
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表