关于 hadoop slot的一篇转载

版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://luobeng.blogbus.com/logs/105015789.html




 hadoop一个节点默认起两个map slot,请问这两个slot是多线程吗?

hadoop-0.21.0 源码中是这样的:

首先看看 org.apache.hadoop.mapred.TaskTracker 类:
=====================================================================================
> 两个类变量 maxMapSlots 和 maxReduceSlots:
-------------------------------------------
    maxMapSlots = conf.getInt(TT_MAP_SLOTS, 2);
    maxReduceSlots = conf.getInt(TT_REDUCE_SLOTS, 2);
  其中 
    public static final String TT_MAP_SLOTS =  "mapreduce.tasktracker.map.tasks.maximum";
    public static final String TT_REDUCE_SLOTS = "mapreduce.tasktracker.reduce.tasks.maximum";
-------------------------------------------
> 类方法 initializeMemoryManagement() 中 ,根据 slots 来决定申请内存的大小
-------------------------------------------
totalMemoryAllottedForTasks =
        maxMapSlots * mapSlotMemorySizeOnTT + maxReduceSlots
            * reduceSlotSizeMemoryOnTT;
-------------------------------------------
> 类方法 TaskTracker.initialize() 中会起两个 TaskLauncher 线程,分别负责启动 Mapper 和 Reduce 任务:
-------------------------------------------
    mapLauncher = new TaskLauncher(TaskType.MAP, maxMapSlots);
    reduceLauncher = new TaskLauncher(TaskType.REDUCE, maxReduceSlots);
-------------------------------------------
=====================================================================================

再看看 org.apache.hadoop.mapred.TaskTracker.TaskLauncher 类,它负责启动 Mapper/Reducer 任务。
=====================================================================================
> 初始化 TaskLauncher 时,需要传入 slots 的数量:
-------------------------------------------
    public TaskLauncher(TaskType taskType, int numSlots) {
      ... ... 
      this.maxSlots = numSlots;
      this.numFreeSlots = new IntWritable(numSlots);
      ... ... 
    }
  特别要注意 numFreeSlots 这个类变量: 
      private IntWritable numFreeSlots;
-------------------------------------------
> TaskLauncher.run() 中,循环地看是否有新的 Task 需要启动,并且看是否有足够的 slots 可用:
-------------------------------------------
  while () {
    while (numFreeSlots.get() < task.getNumSlotsRequired()) {
       .......
    }
    numFreeSlots.set(numFreeSlots.get() - task.getNumSlotsRequired());   // 用完了就减掉
  }
-------------------------------------------
> Task 执行完了以后,需要释放 slots :
-------------------------------------------
    public void addFreeSlots(int numSlots) {
      ... ...
      numFreeSlots.set(numFreeSlots.get() + numSlots);
      ... ...
    }
-------------------------------------------
=====================================================================================


所以,综合上面看,  slots 只是一个逻辑值 ( org.apache.hadoop.mapred.TaskTracker.TaskLauncher.numFreeSlots ),而不是对应着一个线程或者进程。TaskLauncher 会维护这个值,以保证资源使用在控制范围内。
帮助理解的最主要的代码可见 : org.apache.hadoop.mapred.TaskTracker.TaskLauncher.run()  。

Mapper 和 Reducer 都是单独的进程,但是它们与 slots 的关系是这样的:
-------------------------------------------
org.apache.hadoop.mapred.TaskTracker.TaskLauncher.run() {
          ... ...
          //got a free slot. launch the task
          startNewTask(tip);
          ... ...
}
-------------------------------------------
这里的 slots 有点类似 “令牌” 的感觉:申请资源,先获得令牌;释放资源,交还令牌。


> mapper 和 reducer 都是单独的进程?好像有点不对,是单独的线程吧?
是单独的进程。

启动Mapper/Reducer的总的调用路径是:
-------------------------------------------
org.apache.hadoop.mapred.TaskTracker.TaskLauncher.run()
->
org.apache.hadoop.mapred.TaskTracker.startNewTask()
->
org.apache.hadoop.mapred.TaskTracker.launchTaskForJob()
->
org.apache.hadoop.mapred.TaskTracker.TaskInProgress.launchTask() 
->
org.apache.hadoop.mapred.Task.createRunner()  //  抽象方法,具体实现在子类 MapTask 和 ReduceTask 中
   |-> org.apache.hadoop.mapred.MapTask.createRunner()  // 创建 MapTaskRunner 类实例
   |-> org.apache.hadoop.mapred.ReduceTask.createRunner()  // 创建 ReduceTaskRunner 类实例
-------------------------------------------
最终,跟踪到了 MapTaskRunner 和 ReduceTaskRunner 这两个类。

至此,我们看看它们的父类 org.apache.hadoop.mapred.TaskRunner ,以下是类的说明:
-------------------------------------------
/** Base class that runs a task in a separate process.  Tasks are run in a
 * separate process in order to isolate the map/reduce system code from bugs in
 * user supplied map and reduce functions.
 */
-------------------------------------------

TaskRunner 虽然 extends Thread (看起来是个线程),但是真正启动Mapper和Reduce进程的代码在函数 TaskRunner.run() 中:
-------------------------------------------
  public final void run() {
      ... ... 
      launchJvmAndWait(setup, vargs, stdout, stderr, logSize, workDir, env);
      ... ... 
  }
-------------------------------------------
其调用了 TaskRunner.launchJvmAndWait() 方法(在此之前还有些创建文件夹、设置配置参数和环境变量等准备性的操作):
-------------------------------------------
  void launchJvmAndWait(List setup, Vector vargs, File stdout,
      File stderr, long logSize, File workDir, Map env)
      throws InterruptedException {
    jvmManager.launchJvm(this, jvmManager.constructJvmEnv(setup, vargs, stdout,
        stderr, logSize, workDir, env, conf));
    synchronized (lock) {
      while (!done) {
        lock.wait();
      }
    }
  }
-------------------------------------------
上面代码主要是 launch 一个 java虚拟机进程。这也是Hadoop启动代价很高的原因,因为launch虚拟机是比较耗资源的;于是又提供了 Task JVM Reuse机制。

单 独起进程的原因也说得很清楚,就是: isolate the map/reduce system code from bugs in user supplied map and reduce functions。其实就是,通过使用不同的进程空间,进行隔离,防止用户提供的代码中有bug死掉后,造成 TaskTracker  所在进程也死掉(这个死掉了,效果就跟阿凡达里面的发光树被毁了一样)。

Hadoop-0.20.2源码中的实现基本也是差不多的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值