datanode进程的分析(一)

数据存储结点主类。

首先启动一系列服务端口,如接收数据的端口,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("Just sent heartbeat, with name " + localName);

          if (!processCommand(cmds))

            continue ;

        }

        reportReceivedBlocks();

        DatanodeCommand cmd = blockReport() ;

        processCommand(cmd);

 

        // start block scanner

        if ( blockScanner != null && blockScannerThread == null &&

            upgradeManager .isUpgradeCompleted()) {

          LOG .info( "Starting Periodic 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; // invalidate blocks

  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 boolean processCommand(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 a block to another datanode

      transferBlocks(bcmd.getBlocks(), bcmd.getTargets());

      myMetrics.blocksReplicated.inc(bcmd.getBlocks().length);

      break ;

    case DatanodeProtocol. DNA_INVALIDATE :

      //

      // Some local block(s) are obsolete and can be

      // safely garbage-collected.

      //

      Block toDelete[] = 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 the data node

      this .shutdown();

      return false ;

    case DatanodeProtocol. DNA_REGISTER :

      // namenode requested a registration - at start or if NN lost contact

       LOG .info( "DatanodeCommand action: 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( "DatanodeCommand action: DNA_ACCESSKEYUPDATE" );

      if ( isAccessTokenEnabled ) {

        accessTokenHandler .setKeys(((KeyUpdateCommand) cmd).getExportedKeys());

      }

      break ;

    default :

      LOG .warn( "Unknown DatanodeCommand action: " + cmd.getAction());

    }

    return true ;

  }

 

 

reportReceivedBlocks()

DN 类中有二个变量。

private LinkedList<Block> receivedBlockList = new LinkedList<Block>();

  private LinkedList<String> delHints = new LinkedList<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 列表。

未完,待续。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值