datanode进程的分析(一)
来源:互联网 发布:杭州淘宝城三期商业 编辑:程序博客网 时间:2024/05/09 07:41
数据存储结点主类。
首先启动一系列服务端口,如接收数据的端口,web server访问端口等。
然后调用startDataNode()函数去做以下事情。
启动DN的数据接收服务守护线程DataXceiverServer。
循环判断是否需要更新,如参数发生变化了,则需要重新初始化DN。
然后再发送心跳,发送最近接收的block,报告DN当前的block列表给NN。
报告DN当前的所有block列表的时间间隔相对要长很多,默认是1个小时报告一次。
run()
dataXceiverServer.start();
while (shouldRun) {
startDistributedUpgradeIfNeeded();
offerService();
}
offerService()
也是一个循环,首先会计算是否到了心跳时间。
到了下一次心跳时间,则远程调用NN的发送心跳函数sendHeartbeat,会返回相应的值。然后处理返回的值。
当下一次心跳还没到时,则向NN报告最近收到的block。
然后,再向NN报告当前所有的blocks。处理NN返回的值。
如果数据块扫描线程没有启动,则启动它。
每次与NN通信时,都会返回DatanodeCommand命令,然后DN调用processCommand()函数去处理这些命令。
while (shouldRun) {
try {
long startTime = now();
if (startTime - lastHeartbeat > heartBeatInterval) {
lastHeartbeat = startTime;
DatanodeCommand[] cmds = namenode.sendHeartbeat(dnRegistration,
data.getCapacity(),
data.getDfsUsed(),
data.getRemaining(),
xmitsInProgress.get(),
getXceiverCount());
myMetrics.heartbeats.inc(now() - startTime);
//LOG.info("Justsent heartbeat, with name " + localName);
if(!processCommand(cmds))
continue;
}
reportReceivedBlocks();
DatanodeCommand cmd = blockReport();
processCommand(cmd);
// start blockscanner
if (blockScanner != null && blockScannerThread == null &&
upgradeManager.isUpgradeCompleted()){
LOG.info("StartingPeriodic block scanner.");
blockScannerThread = new Daemon(blockScanner);
blockScannerThread.start();
}
long waitTime = heartBeatInterval - (System.currentTimeMillis()- lastHeartbeat);
synchronized(receivedBlockList) {
if (waitTime > 0&& receivedBlockList.size() == 0) {
try {
receivedBlockList.wait(waitTime);
} catch(InterruptedException ie) {
}
}
} // synchronized
}
} // while(shouldRun)
} // offerService
sendHeartbeat()
心跳的时间间隔为参数,默认为3S。
this.heartBeatInterval = conf.getLong("dfs.heartbeat.interval", HEARTBEAT_INTERVAL) * 1000L;
processCommand()
从NN中收到的命令有以下:
final static int DNA_UNKNOWN = 0; // unknown action
final static int DNA_TRANSFER = 1; // transfer blocks to another datanode
final static int DNA_INVALIDATE = 2; // invalidateblocks
final static int DNA_SHUTDOWN = 3; // shutdown node
final static int DNA_REGISTER = 4; // re-register
final static int DNA_FINALIZE = 5; // finalize previous upgrade
final static int DNA_RECOVERBLOCK = 6; // request a block recovery
final static int DNA_ACCESSKEYUPDATE = 7; // update access key
将block传送给其他的DN,则调用BlockSender类将block传送给其他DN。
标识无效的block,调用FSDataset类中的方法去标识数据块状态。
恢复block。
关闭DN。
重新注册DN。
完成升级。
private booleanprocessCommand(DatanodeCommand cmd) throws IOException {
if (cmd == null)
return true;
final BlockCommand bcmd =cmd instanceof BlockCommand? (BlockCommand)cmd: null;
switch(cmd.getAction()) {
case DatanodeProtocol.DNA_TRANSFER:
// Send a copy of ablock to another datanode
transferBlocks(bcmd.getBlocks(), bcmd.getTargets());
myMetrics.blocksReplicated.inc(bcmd.getBlocks().length);
break;
case DatanodeProtocol.DNA_INVALIDATE:
//
// Some localblock(s) are obsolete and can be
// safelygarbage-collected.
//
BlocktoDelete[] = bcmd.getBlocks();
try {
if (blockScanner != null) {
blockScanner.deleteBlocks(toDelete);
}
data.invalidate(toDelete);
} catch(IOException e) {
checkDiskError();
throw e;
}
myMetrics.blocksRemoved.inc(toDelete.length);
break;
case DatanodeProtocol.DNA_SHUTDOWN:
// shut down thedata node
this.shutdown();
return false;
case DatanodeProtocol.DNA_REGISTER:
// namenoderequested a registration - at start or if NN lost contact
LOG.info("DatanodeCommandaction: DNA_REGISTER");
if (shouldRun) {
register();
}
break;
case DatanodeProtocol.DNA_FINALIZE:
storage.finalizeUpgrade();
break;
case UpgradeCommand.UC_ACTION_START_UPGRADE:
// start distributed upgrade here
processDistributedUpgradeCommand((UpgradeCommand)cmd);
break;
case DatanodeProtocol.DNA_RECOVERBLOCK:
recoverBlocks(((BlockRecoveryCommand)cmd).getRecoveringBlocks());
break;
case DatanodeProtocol.DNA_ACCESSKEYUPDATE:
LOG.info("DatanodeCommandaction: DNA_ACCESSKEYUPDATE");
if (isAccessTokenEnabled) {
accessTokenHandler.setKeys(((KeyUpdateCommand)cmd).getExportedKeys());
}
break;
default:
LOG.warn("UnknownDatanodeCommand action: " + cmd.getAction());
}
return true;
}
reportReceivedBlocks()
在DN类中有二个变量。
privateLinkedList<Block> receivedBlockList = newLinkedList<Block>();
privateLinkedList<String> delHints = newLinkedList<String>();
最近收到的blocks。
当完整的接收到一个block时,会将block信息添加到这个队列里。
blockReport()
报告数据块列表的时间间隔参数,默认为60 * 60 * 1000;
this.blockReportInterval =
conf.getLong("dfs.blockreport.intervalMsec", BLOCKREPORT_INTERVAL);
调用FSDataSet类中的getBlockReport()方法来获得正确状态的数据块列表。在该类中专门有个变量来保存数据块列表。
ReplicasMap volumeMap = new ReplicasMap();
同样,当block完成到某个状态后,都会block添加到这个队列中。
同时返回给NN的,finalized状态的block列表。
未完,待续。
- datanode进程的分析(一)
- DataNode的分析
- Hadoop-DataNode的相关分析(1)
- hadoop block源代码分析DataNode部分(一)
- DataNode进程启动后自动关掉的问题的解决
- Hadoop源码分析之读文件时NameNode和DataNode的处理过程 选取datanode详解
- hadoop datanode源码分析
- hadoop datanode源码分析
- hadoop datanode源码分析
- HDFS datanode源码分析
- DataNode之BlockSender分析
- DataNode之DirectoryScanner分析
- Hadoop源码分析之DataNode的启动与停止
- Hadoop源码分析之DataNode的启动与停止
- datanode进程宕掉解决方案
- Ril分析一 rild进程
- Hadoop源码分析DataNode类
- DataNode启动流程源码分析
- Debug 版本 vs Release版本
- 内存访问越界(转)
- QTP(Quick Test Professional)
- vmware tools linux
- mini 2440 编写串口驱动常用名词
- datanode进程的分析(一)
- 硬盘分区表损坏修复实录
- 补码
- C++ GUI Qt 编程(第二版)第8章 Diagram_1(实现主对话框)
- Groovy入门以及配置
- google APIkay test
- 李嘉诚自述发家秘笈 实现买房梦的98个理财忠告
- JAXP 利用xml schema 验证xml的合法性
- 【操作系统】linux--编程技术--嵌入式实验