使用来自 Cloud Storage 的输入的地图任务仅使用一名工作人员

Map tasks with input from Cloud Storage use only one worker

我正在尝试通过 FileInputFormat 使用来自 Google 云存储的文件作为 MapReduce 作业的输入。文件格式为 Avro

作为一个简单的测试,我使用 bdutil 工具部署了一个小型 Hadoop2 集群,由主节点和两个工作节点组成,每个节点有两个插槽。

当 运行 运行作业时,文件被拆分成多个部分。可以通过查看使用偏移量加载数据的日志来验证这一事实。结果,创建了多个地图任务。到目前为止没有异常。

但是那些映射任务不会在工作节点之间分配。相反,两个仅在一个节点上启动,其他节点处于 Scheduled 状态。

我预计每个工作人员有两个映射任务到 运行,因为数据在任何工作人员节点(它在 Cloud Storage 中)都不是本地可用的,这使得它们都是平等的候选人。

为什么会这样?

看来您看到的是 YARN 工作原理的产物之一;与 Hadoop 1 不同,JobTracker 同时有效地扮演 Hadoop 2 的 AppMaster 和 ResourceManager 的角色,在 Hadoop 2 中,ResourceManager(运行 在你的主节点上)实际上将一个全新的 AppMaster 打包到一个 YARN 容器上- 对每个 MapReduce 作业的需求。

此外,另一个稍有变化的概念是,您从来没有完全拥有 "slots",YARN 容器实际上在内存和 CPU 维度上进行调度。这意味着如果打包到 YARN 上的单个任务请求大量内存但只有 1 CPU,它可能会占用资源足迹,否则可能会打包多个 map 或 reduce 任务。

例如,假设您部署了 2 个 worker,每个 n1-standard-2,当 运行 您的 mapreduce:

时,您可能会在 http://<master-ip>:8088/cluster/nodes 下的 ResourceManager 页面上看到类似这样的内容
... Containers  Mem Used    Mem Avail   VCores Used VCores Avail    Version
...     1       5.50 GB     0 B         1           1               2.6.0
...     2       5 GB        512 MB      2           0               2.6.0

在这种情况下,从 ResourceManager 访问 application_master link 显示 ResourceManager 确实被打包到报告 5.5GB Mem Used, 0B Mem Avail, 1 VCores Used 的 VM 上。同样,我发现我的地图任务仅在报告 2 VCores Used.

的工作人员上 运行

一般来说,这意味着如果您最感兴趣的是确保它随着工作人员数量的增加而扩展,则您不必做任何特别的事情;你最终会把你的地图或减少任务打包到 NUM_WORKERS - 1 可能的机器上,而其中一台运行 AppMaster 来完成这项工作。

不过,根据您的工作,这可能会造成浪费。默认设置最适合非常大的作业,在这种情况下,有一个非常大的 AppMaster 是有意义的,以确保它不会 OOM 跟踪大量正在进行的任务。您可以通过覆盖自定义 *_env.sh 文件中的 NODEMANAGER_MEMORY_FRACTIONCORES_PER_MAP_TASKCORES_PER_REDUCE_TASKCORES_PER_APP_MASTER(或内联 hadoop2_env.sh,但与维护 my_overrides_env.sh 之类的文件相比,跟踪升级更难。 bdutil 的 hadoop2_env.sh 中的注释解释了这些设置:

# Fraction of worker memory to be used for YARN containers
NODEMANAGER_MEMORY_FRACTION=0.8

# Decimal number controlling the size of map containers in memory and virtual
# cores. Since by default Hadoop only supports memory based container
# allocation, each map task will be given a container with roughly
# (CORES_PER_MAP_TASK / <total-cores-on-node>) share of the memory available to
# the NodeManager for containers. Thus an n1-standard-4 with CORES_PER_MAP_TASK
# set to 2 would be able to host 4 / 2 = 2 map containers (and no other
# containers). For more details see the script 'libexec/configure-mrv2-mem.py'.
CORES_PER_MAP_TASK=1.0

# Decimal number controlling the size of reduce containers in memory and virtual
# cores. See CORES_PER_MAP_TASK for more details.
CORES_PER_REDUCE_TASK=2.0

# Decimal number controlling the size of application master containers in memory
# and virtual cores. See CORES_PER_MAP_TASK for more details.
CORES_PER_APP_MASTER=2.0

特别是如果你升级到像 n1-standard-4 这样更大的机器,你可以考虑简单地将 NODEMANAGER_MEMORY_FRACTION 修改为一个较小的值。