创建DataNode的入口DataNode.main(String[] args),主要的处理逻辑在方法【DataNode.createDataNode(String[] args, Configuration conf, SecureResources resources)】中,分别初始化DataNode和启动DataNode的守护线程两大步。
一.【DataNode.instantiateDataNode(String[] args,Configuration conf, SecureResources resources) 】初始化DataNode:
1.读取"dfs.data.dir"配置参数,放入dataDirs:String[]中;
2.【DataNode.makeInstance(String[] dataDirs,Configuration conf, SecureResources resources)】
2.1)【FileSystem.getLocal(Configuration conf)】初始化一个LocalFileSystem对象,即本地文件系统对象;
2.2)遍历dataDirs:
2.2.1)调用【DiskChecker.checkDir(LocalFileSystem localFS, Path dir, FsPermission expected)】:
1)【DiskChecker.mkdirsWithExistsAndPermissionCheck(LocalFileSystem localFS,Path dir,FsPermission expected)】:创建${dfs.data.dir}目录并赋上权限;
2)检查此目录是否有读写权限以及是否为目录,否则抛出异常;
2.2.2)对每个路径初始化File对象,并存入dirs:ArrayList<File>队列中;
2.3)【DataNode.DataNode(Configuration conf, AbstractList<File> dataDirs, SecureResources resources)】,初始化DataNode对象;内部调用【DataNode.startDataNode(Configuration conf,AbstractList<File> dataDirs, SecureResources resources)】方法,具体实现步骤如下:
2.3.1)获取NameNode的访问地址,并初始化为InetSocketAddress对象:nameNodeAddr;
1)读取配置文件中的dfs.namenode.servicerpc-address参数的值;若有值则返回;否则进入第2步;
2)读取配置文件中的dfs.namenode.rpc-address参数的值;若有值则返回;否则进入第3步;
3)读取配置文件中的fs.default.name参数的值并返回;
2.3.2)读取配置文件中的参数“dfs.socket.timeout”,“dfs.datanode.socket.write.timeout”,“dfs.datanode.transferTo.allowed”,“dfs.write.packet.size”等配置信息;
2.3.3)获取DataNode的数据块流的读写的地址,配置文件中的参数dfs.datanode.address值或'dfs.datanode.bindAddress':'dfs.datanode.port'值
2.3.4)【new DataStorage()】初始化DataNode.storage变量,主要用于管理数据目录的类,完成格式化,升级,回滚等功能;
2.3.5)读取配置"slave.host.name“;若不为空,则赋值给DataNode.machineName:String;若为空,则读取"dfs.datanode.dns.interface" 和 "dfs.datanode.dns.nameserver",此两个配置缺省均为default,通过【DNS.getDefaultHost(String strInterface, String nameserver)】生成DataNode.machineName变量的值;
2.3.6)通过DataNode.machineName和第2.3.3步的port值 初始化DataNode.dnRegistration:DatanodeRegistration对象;
2.3.7)调用RPC.waitForProxy(...)方法,通过nameNodeAddr网络地址获取与NameNode通信的客户端DataNode.namenode;
2.3.8)【DataNode.handshake()】通过RPC方式调用【NameNode.versionRequest()】,从NameNode获取namespaceid,ctime信息然后封装成NamespaceInfo对象返回;在NameNode端调用【FSNamesystem.getNamespaceInfo()】
2.3.9)【DataStorage.recoverTransitionRead(NamespaceInfo nsInfo, Collection<File> dataDirs, StartupOption startOpt)】
2.3.9.1)遍历形参dataDirs(在第2.2.2步中生成):
1)根据集合中的File对象初始化StorageDirectory对象并存入Storage.storageDirs:List<StorageDirectory>中;
2)【StorageDirectory.analyzeStorage(StartupOption startOpt)】检查所有${dfs.data.dir}目录下文件的一致性,大致思路如下:
2.1)检测${dfs.data.dir}文件夹是否存在,是否有写权限;
2.2)根据VERSION,previous,previous.tmp,finalized.tmp,lastcheckpoint.tmp文件的存在与否来判断文件的状态;
2.3.9.2)遍历Storage.storageDirs集合,调用【DataStorage.doTransition(StorageDirect
一.【DataNode.instantiateDataNode(String[] args,Configuration conf, SecureResources resources) 】初始化DataNode:
1.读取"dfs.data.dir"配置参数,放入dataDirs:String[]中;
2.【DataNode.makeInstance(String[] dataDirs,Configuration conf, SecureResources resources)】
2.1)【FileSystem.getLocal(Configuration conf)】初始化一个LocalFileSystem对象,即本地文件系统对象;
2.2)遍历dataDirs:
2.2.1)调用【DiskChecker.checkDir(LocalFileSystem localFS, Path dir, FsPermission expected)】:
1)【DiskChecker.mkdirsWithExistsAndPermissionCheck(LocalFileSystem localFS,Path dir,FsPermission expected)】:创建${dfs.data.dir}目录并赋上权限;
2)检查此目录是否有读写权限以及是否为目录,否则抛出异常;
2.2.2)对每个路径初始化File对象,并存入dirs:ArrayList<File>队列中;
2.3)【DataNode.DataNode(Configuration conf, AbstractList<File> dataDirs, SecureResources resources)】,初始化DataNode对象;内部调用【DataNode.startDataNode(Configuration conf,AbstractList<File> dataDirs, SecureResources resources)】方法,具体实现步骤如下:
2.3.1)获取NameNode的访问地址,并初始化为InetSocketAddress对象:nameNodeAddr;
1)读取配置文件中的dfs.namenode.servicerpc-address参数的值;若有值则返回;否则进入第2步;
2)读取配置文件中的dfs.namenode.rpc-address参数的值;若有值则返回;否则进入第3步;
3)读取配置文件中的fs.default.name参数的值并返回;
2.3.2)读取配置文件中的参数“dfs.socket.timeout”,“dfs.datanode.socket.write.timeout”,“dfs.datanode.transferTo.allowed”,“dfs.write.packet.size”等配置信息;
2.3.3)获取DataNode的数据块流的读写的地址,配置文件中的参数dfs.datanode.address值或'dfs.datanode.bindAddress':'dfs.datanode.port'值
2.3.4)【new DataStorage()】初始化DataNode.storage变量,主要用于管理数据目录的类,完成格式化,升级,回滚等功能;
2.3.5)读取配置"slave.host.name“;若不为空,则赋值给DataNode.machineName:String;若为空,则读取"dfs.datanode.dns.interface" 和 "dfs.datanode.dns.nameserver",此两个配置缺省均为default,通过【DNS.getDefaultHost(String strInterface, String nameserver)】生成DataNode.machineName变量的值;
2.3.6)通过DataNode.machineName和第2.3.3步的port值 初始化DataNode.dnRegistration:DatanodeRegistration对象;
2.3.7)调用RPC.waitForProxy(...)方法,通过nameNodeAddr网络地址获取与NameNode通信的客户端DataNode.namenode;
2.3.8)【DataNode.handshake()】通过RPC方式调用【NameNode.versionRequest()】,从NameNode获取namespaceid,ctime信息然后封装成NamespaceInfo对象返回;在NameNode端调用【FSNamesystem.getNamespaceInfo()】
2.3.9)【DataStorage.recoverTransitionRead(NamespaceInfo nsInfo, Collection<File> dataDirs, StartupOption startOpt)】
2.3.9.1)遍历形参dataDirs(在第2.2.2步中生成):
1)根据集合中的File对象初始化StorageDirectory对象并存入Storage.storageDirs:List<StorageDirectory>中;
2)【StorageDirectory.analyzeStorage(StartupOption startOpt)】检查所有${dfs.data.dir}目录下文件的一致性,大致思路如下:
2.1)检测${dfs.data.dir}文件夹是否存在,是否有写权限;
2.2)根据VERSION,previous,previous.tmp,finalized.tmp,lastcheckpoint.tmp文件的存在与否来判断文件的状态;
2.3.9.2)遍历Storage.storageDirs集合,调用【DataStorage.doTransition(StorageDirect