Hadoop生态:YARN公平调度与容量调度器性能优化实践指南
一、技术背景与应用场景
随着大数据应用的广泛普及,企业集群中各种类型的作业(批处理、交互式、流式计算)并发运行,对资源调度提出了更高要求。YARN(ResourceManager) 提供了多种调度器(Scheduler)来满足不同场景:
- Capacity Scheduler(容量调度器):基于队列的资源隔离与容量保证,适合多租户或部门配额场景。
- Fair Scheduler(公平调度器):追求资源分配公平性,能动态平衡各作业资源占用,适合资源抢占环境。
在生产环境中,合理地选择与调优调度器可以显著提升资源利用率与作业吞吐量,降低小作业延迟。本文将从核心原理、源码剖析、生产示例及优化建议等方面,系统讲解 YARN 公平调度器与容量调度器的性能优化方法。
二、核心原理深入分析
2.1 容量调度器(Capacity Scheduler)
Capacity Scheduler 基于多级队列体系:
- 根队列(root) 下可配置多个子队列,每个子队列可继续嵌套。
- 每个子队列分配一定百分比资源(capacity),如 root.a = 30%,root.b = 70%。
- 支持队列的最小容量(minimumCapacity)与最大容量(maximumCapacity)控制。
资源分配流程:
- Client 提交应用到某个队列。
- ResourceManager 根据当前总资源与队列 capacity 计算该队列可用资源。
- NodeManager 上的可用容器分配到队列。
- 当队列未用满最小容量且有空闲资源,可动态扩容但不超过最大容量。
2.2 公平调度器(Fair Scheduler)
Fair Scheduler 引入公平共享模型:
- 每个作业(或队列)初始份额(fair share) = 总资源 / 活跃实体数。
- 当某些实体占用资源少于其份额,可让其他实体占用更多;当占用超过份额时,低优先级实体或空闲抢占来恢复公平
核心模块:
- FSQueue(可分层队列)
- FSAppAttempt(作业尝试)
- AllocationModule(分配算法)
公平调度算法:
- 使用最小共享公平性(min-share fairness),轮询分配每个活跃作业一个容器,直到资源耗尽。
- 支持延迟资源抢占(delayScheduling),让短作业优先完成。
三、关键源码解读
以下以 CapacityScheduler 类为例,剖析队列资源计算核心方法:
public class CapacityScheduler extends AbstractYarnScheduler<FiCaSchedulerApp, FiCaSchedulerNode> {
@Override
protected void assignContainers(Resource clusterResource,
ResourceLimits resourceLimits,
List<FiCaSchedulerApp> apps,
List<FiCaSchedulerNode> nodes) {
// 遍历可运行应用
for (FiCaSchedulerApp app : apps) {
CSQueue queue = queueManager.getLeafQueue(app.getQueueName());
// 计算队列允许的最大资源
Resource maxCapRes = queue.getQueueResourceQuotas().getMaxCapacityResource();
// 计算用户可获取资源
Resource headroom = queue.getHeadroom();
if (!Resources.fitsIn(app.getCurrentConsumption(), headroom)) {
continue;
}
// 尝试分配容器
app.allocateClusterResources(...);
}
}
}
从源码可以看出:队列(QueueManager)负责管理多级队列的资源指标,headroom 计算了剩余可用资源。优化时可聚焦:
- 合理设置队列最小/最大容量;
- 精细化队列层级,隔离关键作业;
- 限制单用户最大占用,防止资源抢占。
四、实际应用示例
4.1 生产环境配置
假设某企业有两类作业:批量 ETL(高吞吐、低延迟)与交互式 SQL(低吞吐、高响应)。使用 Capacity Scheduler:
<!-- capacity-scheduler.xml -->
<property>
<name>yarn.scheduler.capacity.root.queues</name>
<value>ETL,SQL</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.ETL.capacity</name>
<value>70</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.SQL.capacity</name>
<value>30</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.ETL.maximum-capacity</name>
<value>90</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.SQL.maximum-capacity</name>
<value>50</value>
</property>
部署后,可通过 Web UI 或 yarn scheduler -status
观察队列资源使用情况。
4.2 延迟抢占配置(Fair Scheduler)
若改用 Fair Scheduler,可在 fair-scheduler.xml
配置:
<allocations>
<queue name="default">
<minResources>1vCore,1GB</minResources>
</queue>
<queue name="interactive">
<minResources>2vCore,4GB</minResources>
<maxResources>10vCore,20GB</maxResources>
</queue>
<queuePlacementPolicy>fair</queuePlacementPolicy>
<preemption>
<timeout>30</timeout> <!-- 30s 延迟抢占 -->
</preemption>
</allocations>
同时在 ResourceManager 启动参数添加:
-Dyarn.resourcemanager.scheduler.class=org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler
-Dyarn.scheduler.fair.preemption=true
上述配置可让短交互式作业优先获取资源,30s 后若未归还资源则触发抢占。
4.3 性能监控与度量
借助 Apache Ambari 或直接通过 RM REST API 获取:
curl http://resourcemanager:8088/ws/v1/cluster/scheduler
可实时查看各队列资源分配比例与抢占信息。结合 Prometheus + Grafana,可进一步绘制资源利用率、作业等待时长等指标。
五、性能特点与优化建议
队列设计原则
- 避免过度嵌套,2-3 级即可;
- 为关键作业预留最小容量,防止关键业务被挤占;
- 合理设置最大容量,防止单队列过度扩张。
抢占与延迟调度
- 对于短作业集群,启用延迟抢占;
- 对于长跑批处理,可关闭抢占减少调度抖动;
- 调整 preemption.timeout 与 preemption.vacate.timeout 平衡抢占及时性。
资源粒度与容器大小
- 根据作业特性调整容器内存与 vCore,太细小导致大量心跳开销;
- 太大则可能造成资源碎片。
监控告警
- 实时监控队列使用率、pendingContainers;
- 对于连续 5 分钟 pending 过高,发送预警。
YARN 调度器集群扩展
- 对于 ResourceManager 单点瓶颈,可考虑使用 Federation 或 HA 模式;
- Fair Scheduler 可配合 Capacity Scheduler 通过 Federation 实现跨集群调度。
通过本文的实践示例与源码剖析,相信读者可以根据自身场景灵活选择调度器并进行参数调优,提升整个 Hadoop 集群的资源利用率与作业吞吐能力。