【大数据】Hadoop_Yarn

一、Yarn资源调度器

1. Yarn概述

Yarn是一个资源调度平台,负责为运算程序提供服务器运算资源,相当于一个分布式的操作系统平台,而MapReduce等运算程序则相当于运行于操作系统之上的应用程序。

Yarn 是一个通用的资源管理系统和调度平台,可以为上层应用提供统一的资源管理和调度,它的引入为集群在利用率、资源统一管理和数据共享等方面带来了巨大好处。

虽然 Yarn 属于Hadoop的一部分,但是Yarn不仅仅能运行 MapReduce,还可以运行 Tez、HBase、Spark、Flink等等程序,理论上支持各种计算程序。Yarn不关心你做的什么,只负责管理资源(内存 和 CPU)。

2. Yarn基础架构

Yarn由 ResourceManager、NodeManager、ApplicationMaster 和 Container 等组件构成。
在这里插入图片描述

  • ResourceManager、NodeManager 是集群物理层面的组件,在Hadoop集群搭建过程中需要明确分配Resourcemanager是哪台服务器、NodeManager是哪台服务器。

  • ApplicationMaster 简称 AppMaster。在 MapReduce程序中的 MRAppMaster 就是 AppMaster的一个具体实现。属于 App
    应用层面,Yarn不关心该组件,而是由具体的应用程序(MapReduce、Spark等)去具体实现。

  • ResourceManager、NodeManager、AppMaster 合称 Yarn的三大组件。

  • Container容器:是硬件资源的抽象,多个程序之间就可以隔离运行。

3. Yarn工作机制

在这里插入图片描述

详细步骤:

  1. MR 程序提交到客户端所在的节点。
  2. YarnRunner 向 ResourceManager 申请一个 Application。
  3. RM 将该应用程序的资源路径返回给 YarnRunner。
  4. 该程序将运行所需资源提交到 HDFS 上。
  5. 程序资源提交完毕后,申请运行 mrAppMaster。
  6. RM 将用户的请求初始化成一个 Task。
  7. 其中一个 NodeManager 领取到 Task 任务。
  8. 该 NodeManager 创建容器 Container,并产生 MRAppmaster。
  9. Container 从 HDFS 上拷贝资源到本地。
  10. MRAppmaster 向 RM 申请运行 MapTask 资源。
  11. RM 将运行 MapTask 任务分配给另外两个 NodeManager,另两个 NodeManager 分别领取任务并创建容器。
  12. MR 向两个接收到任务的 NodeManager 发送程序启动脚本,这两个 NodeManager分别启动 MapTask,MapTask 对数据分区排序。
  13. MrAppMaster 等待所有 MapTask 运行完毕后,向 RM 申请容器,运行ReduceTask。
  14. ReduceTask 向 MapTask 获取相应分区的数据。
  15. 程序运行完毕后,MR 会向 RM 申请注销自己。

4. 作业提交过程

HDFS、YARN、MapReduce三者关系
在这里插入图片描述

作业提交过程之YARN
在这里插入图片描述

作业提交过程之HDFS & MapReduce
在这里插入图片描述

5. Yarn调度器和调度算法

  • 调度器(Resource Scheduler)是属于ResourceManager内部的一个组件,当有多个 job 提交过来的时候,使用调度器进行调度。

  • 在理想情况下,应用程序提出的请求都将立即得到Yarn批准。但在实际中,资源是有限的,并且繁忙的在群集上。Yarn调度程序的工作是根据一些定义的策略为应用程序分配资源。

  • 在Yarn中,负责给应用程序分配资源的就是Scheduler,它是ResourceMananger的核心组件之一。

  • 目前,Hadoop 作业调度器主要有三种:FIFO、容量(Capacity Scheduler)和公平(Fair Scheduler)。Apache Hadoop3.1.3 默认的资源调度器是 Capacity Scheduler。CDH
    框架默认调度器是 Fair Scheduler。可以通过配置文件配置:yarn-site.xml

5.1 先进先出调度器(FIFO)

FIFO 调度器(First In First Out):单队列,根据提交作业的先后顺序,先来先服务。
优点:简单易懂
缺点:不支持多队列,生产环境很少使用

在这里插入图片描述

FIFO是 Hadoop 1.x 中的 JobTracker 原有的调度器实现,在Yarn中保留了下来。实际生产中用到大数据的场景都是高并发的,所以一般不会采用这种调度器。

5.2 容量调度器(Capacity Scheduler)

Capacity Scheduler 是 Yahoo 开发的多用户调度器,是Apache版的 Hadoop 3.x 的默认调度策略。该策略允许多个组织共享整个集群资源,每个组织可以获得集群的一部分计算能力。通过为每个组织分配专门的队列,然后再为每个队列分配一定的集群资源,这样整个集群就可以通过设置多个队列的方式给多个组织提供服务了。

容量调度器特点
在这里插入图片描述

容量调度器资源分配算法
在这里插入图片描述

5.3 公平调度器(Fair Scheduler)

Fair Scheduler公平调度器是 Facebook 开发的多用户调度器。 提供了Yarn应用程序 公平地共享大型集群中资源 的另一种形式。使所有应用在平均情况下随着时间的流式可以获得相等的资源份额。
公平调度可以在多个丢列建工作,允许资源共享和抢占。

公平调度器特点
在这里插入图片描述

缺额
在这里插入图片描述

缺额产生的原因:
如果目前一个队列中有4个job正在运行,此时来了第5个job。理想情况下,如果使用公平调度器,第5个job进来之后马上就和前4个job平分整个队列的资源。
但是实际情况中,job5进来之后,只能先得到一点点资源,等待一段时间让其他job释放出一些资源出来。此时,第5个job应该分配的资源和实际得到的资源之间的差额就是缺额。

公平调度器设计目标是:在时间尺度上,所有作业获得公平的资源。调度器会优先为缺额大的作业分配资源 。
公平调度器队列资源分配方式

在这里插入图片描述
在这里插入图片描述

公平调度器资源分配算法
在这里插入图片描述

在这里插入图片描述

6. Yarn常用命令

Yarn 状态的查询,除了可以在 hadoop103:8088 页面查看外,还可以通过命令操作。

6.1 yarn application查看任务

列出所有 Application:

yarn application -list

根据 Application 状态过滤(所有状态:ALL、NEW、NEW_SAVING、SUBMITTED、ACCEPTED、RUNNING、FINISHED、FAILED、KILLED)

 # yarn application -list -appStates <ALL | NEW | NEW_SAVING | SUBMITTED | ACCEPTED | RUNNING | FINISHED | FAILED | KILLED>
yarn application -list -appStates FINISHED

Kill 掉 Application:

# yarn application -kill <application_id>
yarn application -kill application_1653269087987_0001

6.2 yarn logs查看日志

查询 Application 日志:

# yarn logs -applicationId <application_id>
yarn logs -applicationId application_1653269087987_0001

查询 Container 日志:

# yarn logs -applicationId <application_id> -containerId <container_id>
yarn logs -applicationId application_1653269087987_0001 -containerId container_1653269087987_0001_01_000001

6.3 yarn applicationattempt 查看尝试运行的任务

列出所有 Application 尝试的列表:

# yarn applicationattempt -list <application_id>
yarn applicationattempt -list application_1653269087987_0001

打印 ApplicationAttempt状态:

# yarn applicationattempt -status <AppAttempt_id>
yarn applicationattempt -status appattempt_1653269087987_0001_000001

6.4 yarn container查看容器

列出所有 Container:

# yarn container -list <AppAttempt_id>
yarn container -list appattempt_1653269087987_0001_000001

打印Container状态:

# yarn container -status <container_id>
yarn container -status appattempt_1653269087987_0001_000001

只有在任务跑的途中才能看到 container 的状态

6.5 yarn node查看节点状态

列出所有节点:

yarn node -list -all

6.6 yarn rmadmin更新配置

加载队列配置:

yarn rmadmin -refreshQueues

6.7 yarn queue查看队列

打印队列信息:

# yarn queue -status <queue_name>
# 容量调度器、公平调度器都有一个default队列,可以查看该队列信息。也可以根据实际情况增加队列
yarn queue -status default

7. Yarn 生产环境核心参数

在这里插入图片描述

二、Yarn案例实操

1. Yarn生产环境核心参数配置案例

需求:从 1G 数据中,统计每个单词出现次数。服务器 3 台,每台配置 4G 内存,4 核CPU,4 线程。
1G / 128m = 8 个 MapTask;1 个 ReduceTask;1 个 mrAppMaster;平均每个节点运行 10 个 / 3 台 ≈ 3 个任务(4 3 3)

修改 yarn-site.xml 配置参数如下:

<property>
    <!-- 选择调度器,例如容量调度器 -->
    <description>The class to use as the resource scheduler.</description>
    <name>yarn.resourcemanager.scheduler.class</name>
    <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler</value>
</property>

<property>
    <!-- ResourceManager处理器调度器请求的线程数量,默认50 -->
    <!-- 如果提交的任务数量大于50,可以增加该值,但是不能超过 3台 * 4线程 = 12 线程(去除其他应用程序,实际上不能超过8) -->
    <description>Number of threads to handle scheduler interface.</description>
    <name>yarn.resourcemanager.scheduler.client.thread-count</name>
    <value>8</value>
</property>

<property>
    <!-- 是否让yarn自动检测硬件进行配置,默认false -->
    <!-- 如果该节点有很多其他应用程序,建议手动配置 -->
    <!-- 如果该节点没有其他应用程序,可以采用自动配置 -->
    <description>Enable auto-detection of node capabilities such as memory and CPU.</description>
    <name>yarn.nodemanager.resource.detect-hardware-capabilities</name>
    <value>false</value>
</property>

<property>
    <!-- 是否将虚拟核数当做cpu核数,默认值false,采用物理核数 -->
    <description>Flag to determine if logical processors(such as hyperthreads) should be counted as cores. Only applicable on Linux when yarn.nodemanager.resource.cpu-vcores is set to -1 and yarn.nodemanager.resource.detect-hardware-capabilities is true.
    </description>
    <name>yarn.nodemanager.resource.count-logical-processors-as-cores</name>
    <value>false</value>
</property>

<property>
    <!-- 虚拟核数和物理核数乘数,默认值1.0 -->
    <!-- 此处我们的服务器时4核4线程,即核数和线程数比值为1.0 -->
    <description>Multiplier to determine how to convert phyiscal cores to vcores. This value is used if yarn.nodemanager.resource.cpu-vcores is set to -1(which implies auto-calculate vcores) and yarn.nodemanager.resource.detect-hardware-capabilities is set to true. The number of vcores will be calculated as number of CPUs * multiplier.
    </description>
    <name>yarn.nodemanager.resource.pcores-vcores-multiplier</name>
    <value>1.0</value>
</property>

<property>
    <!-- NodeManager使用内存,默认设置的 -1,即不开启硬件检测时默认8G,开启的话自动计算 -->
    <!-- 这里我们服务器是4G,需要调整为4G -->
    <description>Amount of physical memory, in MB, that can be allocated  for containers. If set to -1 and yarn.nodemanager.resource.detect-hardware-capabilities is true, it is automatically calculated(in case of Windows and Linux). In other cases, the default is 8192MB.
    </description>
    <name>yarn.nodemanager.resource.memory-mb</name>
    <value>4096</value>
</property>

<property>
    <!-- NodeManager的CPU核数,默认值-1。即不开启硬件检测时默认8,开启的话自动计算-->
    <!-- 此处我们的服务器只有4核4线程 -->
    <description>Number of vcores that can be allocated for containers. This is used by the RM scheduler when allocating resources for containers. This is not used to limit the number of CPUs used by YARN containers. If it is set to -1 and yarn.nodemanager.resource.detect-hardware-capabilities is true, it is automatically determined from the hardware in case of Windows and Linux. In other cases, number of vcores is 8 by default.</description>
    <name>yarn.nodemanager.resource.cpu-vcores</name>
    <value>4</value>
</property>

<property>
    <!-- 容器最小内存,默认1G -->
    <description>The minimum allocation for every container request at the RM in MBs. Memory requests lower than this will be set to the value of this property. Additionally, a node manager that is configured to have less memory than this value will be shut down by the resource manager.</description>
    <name>yarn.scheduler.minimum-allocation-mb</name>
    <value>1024</value>
</property>

<property>
    <!-- 容器最大内存,默认8G -->
    <!-- 此处我们的服务器只有4G内存,根据前面分析,每台服务器要启动3个容器,所以容器最大内存可以修改为 2G -->
    <description>The maximum allocation for every container request at the RM in MBs. Memory requests higher than this will throw an InvalidResourceRequestException.</description>
    <name>yarn.scheduler.maximum-allocation-mb</name>
    <value>2048</value>
</property>

<property>
    <!-- 容器最小CPU核数,默认1个 -->
    <description>The minimum allocation for every container request at the RM in terms of virtual CPU cores. Requests lower than this will be set to the value of this property. Additionally, a node manager that is configured to have fewer virtual cores than this value will be shut down by the resource manager.</description>
    <name>yarn.scheduler.minimum-allocation-vcores</name>
    <value>1</value>
</property>

<property>
    <!-- 容器最大CPU核数,默认值4 -->
    <!-- 此处我们的服务器是4核,根据前面分析每台服务器要启动3个容器,所以容器最大CPU核数设置为2个 -->
    <description>The maximum allocation for every container request at the RM in terms of virtual CPU cores. Requests higher than this will throw an InvalidResourceRequestException</description>
    <name>yarn.scheduler.maximum-allocation-vcores</name>
    <value>2</value>
</property>

<property>
    <!-- 虚拟内存检测,默认打开 -->
    <!-- 如果是 CentOS 7 + JDK 8,建议关闭该检测 -->
    <description>Whether virtual memory limits will be enforced for containers.</description>
    <name>yarn.nodemanager.vmem-check-enabled</name>
    <value>false</value>
</property>

<property>
	<!-- 虚拟内存和物理内存比例(用作虚拟内存检测的限制),默认值2.1 -->
    <description>Ratio between virtual memory to physical memory when setting memory limits for containers. Container allocations are expressed in terms of physical memory, and virtual memory usage is allowed to exceed this allocation by this ratio.
    </description>
    <name>yarn.nodemanager.vmem-pmem-ratio</name>
    <value>2.1</value>
</property>

关闭虚拟内存检查原因:
在这里插入图片描述

在CentOS 7 + JDK 8时,Linux会为 Java 进程预留一部分虚拟内存(占了很大一部分),供 JDK 使用,但是 JDK 8没有使用这部分,而是使用了剩下的部分(图上Java堆的部分),就导致浪费了很大的内存。而且因为剩下的这部分内存的量很少,不到4G,就会导致虚拟内存很容易超过了上限,如果实际使用的vmem超过了vmemLimit或者olderThanAge就可能 kill 掉该进程 。

修改yarn-site.xml后,分发到集群所有节点。然后重启yarn:sbin/stop-yarn.sh、sbin/start-yarn.sh

2. 容量调度器多队列提交案例

生产环境配置调度器多队列:

  • 调度器默认只有1个default队列,不能满足生产要求
  • 可以按照框架区分多队列,例如创建:hive队列、spark队列、flink队列等,每个框架的任务放入指定的队列(企业里面很少使用这中方式)
  • 可以按照业务模块区分多队列,例如创建:登录模块队列、购物车队列、下单队列、部门1队列、部门2队列等

创建多队列的优势:

  • 防止程序中出现递归死循环等代码,把所有的资源全部耗尽
  • 实现任务的 降级 使用,特殊时期可以保证重要的任务队列资源充足

需求:default 队列占总内存的 40%,最大资源容量占总资源 60%,hive 队列占总内存的 60%,最大资源容量占总资源 80%,配置队列优先级。

2.1 多队列配置

配置多队列的容量调度器,在 $HADOOP_HOME/etc/hadoop/capacity-scheduler.xml配置文件中配置。
capacity-scheduler.xml中修改配置:
(1)修改如下配置

<!-- 指定多队列,增加 hive 队列 -->
<property>
	<name>yarn.scheduler.capacity.root.queues</name>
 	<value>default,hive</value>
 	<description>
		The queues at the this level (root is the root queue).
 	</description>
</property>

<!-- 降低 default 队列资源额定容量为 40%,默认 100% -->
<property>
 	<name>yarn.scheduler.capacity.root.default.capacity</name>
 	<value>40</value>
</property>

<!-- 降低 default 队列资源最大容量为 60%,默认 100% -->
<property>
 	<name>yarn.scheduler.capacity.root.default.maximum-capacity</name>
 	<value>60</value>
</property>

(2)为新加队列添加必要属性:

<!-- 指定 hive 队列的资源额定容量 -->
<property>
 	<name>yarn.scheduler.capacity.root.hive.capacity</name>
 	<value>60</value>
</property>

<!-- 用户最多可以使用队列多少资源,1 表示 -->
<property>
 	<name>yarn.scheduler.capacity.root.hive.user-limit-factor</name>
 	<value>1</value>
</property>

<!-- 指定 hive 队列的资源最大容量 -->
<property>
 	<name>yarn.scheduler.capacity.root.hive.maximum-capacity</name>
 	<value>80</value>
</property>

<!-- 启动 hive 队列 -->
<property>
 	<name>yarn.scheduler.capacity.root.hive.state</name>
 	<value>RUNNING</value>
</property>

<!-- 哪些用户有权向队列提交作业 -->
<property>
 <name>yarn.scheduler.capacity.root.hive.acl_submit_applications</name>
 <value>*</value>
</property>
<!-- 哪些用户有权操作队列,管理员权限(查看/杀死) -->
<property>
 <name>yarn.scheduler.capacity.root.hive.acl_administer_queue</name>
 <value>*</value>
</property>

<!-- 哪些用户有权配置提交任务优先级 -->
<property>
	<name>yarn.scheduler.capacity.root.hive.acl_application_max_priority</nam
e>
 	<value>*</value>
</property>

<!-- 任务的超时时间设置:yarn application -appId appId -updateLifetime Timeout -->
<!-- 如果 application 指定了超时时间,则提交到该队列的 application 能够指定的最大超时时间不能超过该值。-->
<property>
 	<name>yarn.scheduler.capacity.root.hive.maximum-application lifetime</name>
 	<value>-1</value>
</property>

<!-- 如果 application 没指定超时时间,则用 default-application-lifetime 作为默认值 -->
<property>
 	<name>yarn.scheduler.capacity.root.hive.default-application lifetime</name>
 	<value>-1</value>
</property>

修改好配置文件后,分发到集群中其他节点。

如果此时Yarn集群正在启动着,可以执行刷新队列配置信息命令,不需要重启集群:

# 刷新Yarn队列配置信息
# yarn rmadmin不能刷新 yarn-site.xml。如果修改了 yarn-site.xml,只能重启Yarn集群
yarn rmadmin -refreshQueues

启动wordcount程序,指定提交的队列:

# 指定提交到hive队列
# -D 运行时改变参数值
hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.6.jar wordcount -D mapreduce.job.queuename=hive /input /output

2.2 任务优先级配置

容量调度器支持任务优先级的配置,在资源紧张时,优先级高的任务将优先获取资源。 默认情况下,Yarn将所有任务的优先级限制为0,若想使用任务的优先级功能,必须开放该限制。

修改yarn-site.xml,增加参数:

<property>
    <!-- 设置Yarn的任务优先级,默认值0 -->
    <!-- 设置5,表示我们可以有5个优先级:0/1/2/3/4/5,数字越大优先级越高 -->
    <name>yarn.cluster.max-application-priority</name>
    <value>5</value>
</property>

分发到集群其他节点。重启Yarn集群:

sbin/stop-yarn.sh
sbin/start-yarn.sh

当集群中资源不足出现排队时,可以通过调整任务的优先级达到优先执行的目的:

# 在任务启动时就指定任务的优先级
hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.6.jar wordcount -D mapreduce.job.priority=5 /input /output

# 也可以通过命令修改正在执行的任务的优先级
yarn application -appID <app_id> -updatePriority 5

3. 公平调度器案例

创建两个队列,分别是 test 和 hua(以用户所属组命名)。期望实现以下效果:若用户提交任务时指定队列,则任务提交到指定队列运行;若未指定队列,test 用户提交的任务到 root.group.test 队列运行,hua 提交的任务到 root.group.hua 队列运行(注:group 为用户所属组)。

公平调度器的配置涉及到两个文件,一个是 yarn-site.xml,另一个是公平调度器队列分配文件 fair-scheduler.xml(文件名可自定义)。
修改yarn-site.xml,进行以下配置:

<property>
    <!-- 使用公平调度器 -->
    <name>yarn.resourcemanager.scheduler.class</name>
    <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value>
</property>

<property>
    <!-- 声明公平调度器队列分配的配置文件 -->
    <name>yarn.scheduler.fair.allocation.file</name>
    <value>/opt/module/hadoop-3.2.3/etc/hadoop/fair-scheduler.xml</value>
</property>

<property>
    <!-- 禁止队列间资源抢占 -->
    <name>yarn.scheduler.fair.preemption</name>
    <value>false</value>
</property>

配置 fair-scheduler.xml:

<?xml version="1.0"?>
<allocations>
    <!-- 单个队列中 Application Master占用资源的最大比例,取值 0-1,企业一般配置 0.1 -->
	<queueMaxAMShareDefault>0.5</queueMaxAMShareDefault>
    <!-- 单个队列最大资源的默认值 test tenger default -->
    <queueMaxResourcesDefault>4096mb,4vcores</queueMaxResourcesDefault>
    
    <!-- 增加一个队列test -->
    <queue name="test">
        <!-- 队列最小资源 -->
        <minResources>2048mb,2vcores</minResources>
        <!-- 队列最大资源 -->
        <maxResources>4096mb,4vcores</maxResources>
        <!-- 队列中最多同时运行的应用数,默认50,根据线程数配置 -->
        <maxRunningApps>4</maxRunningApps>
        <!-- 队列中 Application Master 占用资源的最大比例 -->
        <maxAMShare>0.5</maxAMShare>
        <!-- 该队列资源权重,默认值1.0 -->
        <weight>1.0</weight>
        <!-- 队列内部的资源分配策略 -->
        <schedulingPolicy>fair</schedulingPolicy>
    </queue>
    
    <!-- 增加一个队列tengyer -->
    <!-- 当type设置为parent时,它会成为父队列 -->
    <queue name="tengyer" type="parent">
        <!-- 队列最小资源 -->
        <minResources>2048mb,2vcores</minResources>
        <!-- 队列最大资源 -->
        <maxResources>4096mb,4vcores</maxResources>
        <!-- 队列中最多同时运行的应用数,默认50,根据线程数配置 -->
        <maxRunningApps>4</maxRunningApps>
        <!-- 队列中 Application Master, maxAMShare只能用于叶子队列,不能用于父队列。所以此处不能配置maxAMShare,否则ResourceMananger启动不了。 -->
        <!--<maxAMShare>0.5</maxAMShare>-->
        <!-- 该队列资源权重,默认值1.0 -->
        <weight>1.0</weight>
        <!-- 队列内部的资源分配策略 -->
        <schedulingPolicy>fair</schedulingPolicy>
    </queue>
    
    <!-- 任务队列分配策略,可配置多层规则,从第一个规则开始匹配,直到匹配成功 -->
    <queuePlacementPolicy>
        <!-- 任务队列分配策略,如果未指定提交队列,则继续匹配下一个规则;false表示:如果指定队列不存在,不允许自动创建 -->
        <rule name="specified" create="false" />
        <!-- 提交到 root.group.username 队列,若 root.group 不存在,不允许自动创建;若 root.group.user 不存在,允许自动创建 -->
        <rule name="nestedUserQueue" create="true">
            <rule name="primaryGroup" create="false" />
        </rule>
        <!-- 最后一个规则必须是reject或者default。reject表示如果前面的条件都不满足,则拒绝创建队列,提交失败。default表示把任务提交到default队列 -->
        <!-- 或者配置成默认: name="default" queue="指定一个默认队列" -->
        <rule name="reject" />        
    </queuePlacementPolicy>
</allocations>

将配置文件分发到集群其他节点服务器。重启yarn集群。

根据前面配置的策略,如果不指定队列,则提交到对应用户名称的队列,即root.hua.hua队列(root.用户组.用户名):

hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.6.jar wordcount /input /output

4. Yarn的Tool接口

以上面配置好的公平调度器为例,执行我们之前自己编写的WordCount程序:

hadoop jar MapReduceDemo-1.0-SNAPSHOT.jar com.study.mapreduce.wordcount.WordCountDriver /input/ /output/

此时,程序可以正常执行,根据公平调度器配置的策略使用 root.hua.hua 调度器运行。
但是如果我们想要使用 -D mapreduce.job.queuename=root.test 指定使用其他调度器,就可能会出现问题。

因为我们自己编写的WordCount程序中,通过参数位置取的输出路径加了-D参数后,shell的参数个数、位置发生了变化,args[0]、args[1]获取的参数就变了,所以程序就报错了。为了让自己编写的程序也可以动态修改参数,就可以使用 Yarn 的 Tool 接口。

需求:自己写的程序也可以动态修改参数。编写 Yarn 的 Tool 接口。

创建Maven项目,加入hadoop-client依赖:

<dependencies>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-client</artifactId>
        <version>3.3.6</version>
    </dependency>
</dependencies>

编写核心类,实现Tool接口:

package com.study.yarn;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.Tool;

public class WordCount implements Tool {
    private Configuration conf;

    /**
     * 驱动。和以前的WordCountDriver几乎一样,区别就是Configuration不再是直接生成,而是通过setConf()方法传入
     */
    @Override
    public int run(String[] args) throws Exception {
        Job job = Job.getInstance(conf);

        job.setJarByClass(WordCountDriver.class);
        job.setMapperClass(WordCountMapper.class);
        job.setReducerClass(WordCountReducer.class);

        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        FileInputFormat.setInputPaths(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));

        return job.waitForCompletion(true) ? 0 : 1;
    }

    @Override
    public void setConf(Configuration conf) {
        this.conf = conf;
    }

    @Override
    public Configuration getConf() {
        return conf;
    }
}

和以前一样编写Mapper、Reducer 。
编写WordCountDriver驱动:

package com.study.yarn;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;

public class WordCountDriver {
    public static void main(String[] args) throws Exception{
        // 创建配置信息
        Configuration conf = new Configuration();

        // 使用ToolRunner进行运行。
        // ToolRunner会将args中的-D参数进行转换,将剩余的参数作为args送到run方法。
        Tool tool = new WordCount();
        ToolRunner.run(conf, tool, args);
    }
}

执行maven的package打包,将打包好的jar包上传到hadoop服务器。

首先使用正常的不传入-D参数的命令进行测试,程序可以正常执行:

hadoop jar YarnDemo-1.0-SNAPSHOT.jar com.study.yarn.WordCountDriver /input/ /output/

然后在中间加入-D参数再进行测试,程序依然可以正常执行:

hadoop jar YarnDemo-1.0-SNAPSHOT.jar com.study.yarn.WordCountDriver -D mapreduce.job.queuename=root.test  /input/ /output/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值