【原创】DataNode源码演绎 第一回

楔子

前几天,笔者解决DataNode节点宕机过程当中,在初期并不知道是由于Centos网卡驱动不兼容形成的系统死机。故将Nodedata源码翻出来所有看了一遍。有些心得,略写一二,各位看官见笑了。java

第一回 混沌未分天地乱,茫茫渺渺无人见。  

笔者以源码跟踪的方式阐述了DataNode运行过程,若有偏颇之处实在是由于笔者水平过低,请看官留下真知灼见,做为往后相见约守。笔者为了阐述清晰只截取了部分相关代码,完整的代码请各位参考源码。node

main函数是一个程序的入口,也是出口,全部的一切,从这里开始,也从这里结束。框架

public class      DataNode 
       extends    Configured 
       implements InterDatanodeProtocol, 
                  ClientDatanodeProtocol, 
                  FSConstants, 
                  Runnable, 
                  DataNodeMXBean 
{
  public static void main(String args[]) 
 {
   secureMain(args, null);
 } 
}

在代码中,若是调用方法的所属类不属于DataNode,笔者会明确的标识出来,不然调用的方法都是在类DataNode中声明和定义的。 函数

public static void secureMain(String [] args, SecureResources resources) 
{
  DataNode datanode = createDataNode(args, null, resources);
  if (datanode != null)    
    datanode.join();       
  System.exit(0);          
}

在静态方法secureMain中,DataNode变量对象datanode被建立。话分两头,咱们先看datanode.join()方法,它作的就是静静的等待,等待线程终止,等待一切终止。oop

void join() 
{
  dataNodeThread.join();
}

话在说回来,继续看createDataNode方法中发生的事情。this

DataNode createDataNode(String args[],Configuration conf,...) 
{
    DataNode dn = instantiateDataNode(args, conf, resources);
    runDatanodeDaemon(dn);  
    return dn;                                          
}

createDataNode方法中会实例化一个Datanode对象出来,事实上实例化一个对象还须要不少的步骤和准备,这些事件将在instantiateDataNode()方法中演绎。spa

public static DataNode instantiateDataNode(String             args[],
                                             Configuration      conf, 
                                             SecureResources    resources) 
throws IOException 
{
    DefaultMetricsSystem.initialize("DataNode");
    return makeInstance(dataDirs, conf, resources);
}
public static DataNode makeInstance(String[]        dataDirs, 
		                   Configuration   conf, 
                                     SecureResources resources) 
 throws IOException 
 {
    UserGroupInformation.setConfiguration(conf);
    LocalFileSystem localFS        = FileSystem.getLocal(conf);
    ArrayList<File> dirs           = new ArrayList<File>();
    return new DataNode(conf, dirs, resources);
    return null;
 }


在makeInstance()函数中,真正的new( )出一个DataNode类型的对象,而且马上开始初始化DataNode类的成员变量和调用DataNode类的构造函数。其中在DataNode中比较重要的成员变量有如下几个:线程

public FSDatasetInterface data = null;

在datanode类中成员变量data其实是FSDataset类型,FSDataset类型用来提供数据存储功能,FSDataset实现了FSDatasetInterface接口 , 对于Block的全部操做都要通过data成员变量管理在这个datanode上存储的block。 code

private DataStorage storage = null;

 Datanode节点利用DataStorage类型的storage对象对本身的全部存储路径进行统一管理。DataStorage主要在Datanode节点启动时扮演重要的角色。orm

public Server ipcServer;

DataNode启动的时候,会建立一个ipcServer这个ipcServerHadoopipc框架的Server实例,主要是在DataNodeDataNode之间recover block时使用,recover block会在两个地方发生,一个是namenode返回的recover命令 ,  一个是DFSClient写数据时遇到DataNode错误时触发。

在成员变量初始化完成以后调用DataNode的构造函数

DataNode(final Configuration conf,final  AbstractList<File> dataDirs,SecureResources resources)                                         
{
  startDataNode(conf, dataDirs,resources);                                   
}

在构造函数中,调用startDataNode方法 

void startDataNode(Configuration            conf, 
                      AbstractList<File>    dataDirs, 
                      SecureResources       resources  )                                                        

{  
  storage                = new DataStorage();                                 
  this.threadGroup       = new ThreadGrou("dataXceiverServer");              
  this.dataXceiverServer = new Daemon(threadGroup,  new DataXceiverServer(ss, conf, this));            
  this.threadGroup.setDaemon(true);
  storage.recoverTransitionRead(nsInfo, dataDirs, startOpt);                   
  this.dnRegistration.setStorageInfo(storage);                        
  this.data = new FSDataset(storage, conf);             
  this.infoServer.start(); 
  blockScanner = new DataBlockScanner(this, (FSDataset)data, conf);        
}

在startDataNode方法中还storage、data、dataXceiverServer、DataBlockScanner都有各自的任务。下次继续说。

相关文章
相关标签/搜索