DevilKing's blog

冷灯看剑,剑上几分功名?炉香无需计苍生,纵一穿烟逝,万丈云埋,孤阳还照古陵

0%

Yarn Schedule

原文链接

FairScheduler/CapacityScheduler

采用层级树的方式,FairScheduler通过这样一棵资源树,维护了整个集群的资源使用情况。资源树中的每一个叶子节点都挂载了此时正在这个队列上运行、或者正在申请运行的应用。FairScheduler只需要对这个树进行适当遍历,就可以知道任何一个资源队列当前有哪些应用在运行、队列当前还剩下多少资源、已经使用多少资源等

###心跳调度

NM通过心跳的方式定期向RM汇报自身状态,

###持续调度

不用等待NodeManager向ResourceManager发送心跳才进行任务调度,而是由一个独立的线程进行实时的资源分配等调度,与NodeManager的心跳出发的调度相互异步并行进行。当心跳到来,只需要把调度结果通过心跳响应告诉对应的NodeManager即可

两种触发机制不同的地方只有两个:

调度时机:心跳调度仅仅发生在收到了某个NodeManager的心跳信息的情况下,持续调度则不依赖与NodeManager的心跳通信,是连续发生的,当心跳到来,会将调度结果直接返回给NodeManager;

调度范围:心跳调度下,当收到某个节点的心跳,就对这个节点且仅仅对这个节点进行一次调度。持续调度的每一轮,是会遍历当前集群的所有节点,每个节点依次进行一次调度,保证一轮下来每个节点都被公平的调度一次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void continuousSchedulingAttempt() throws InterruptedException {
long start = getClock().getTime();
List<NodeId> nodeIdList = new ArrayList<NodeId>(nodes.keySet());
//进行调度以前,先对节点根据剩余资源的多少进行排序,从而让资源更充裕的节点先得到调度
//这样我们更容易让所有节点的资源能够被均匀分配,而不会因为某些节点总是先被调度所以总是比
//后调度的节点的资源使用率更高
synchronized (this) {
Collections.sort(nodeIdList, nodeAvailableResourceComparator);
}
// 遍历所有节点,依次对每一个节点进行一次调度
for (NodeId nodeId : nodeIdList) {
//FSSchedulerNode是FairScheduler视角下的一个节点
FSSchedulerNode node = getFSSchedulerNode(nodeId);
try {
//判断
if (node != null && Resources.fitsIn(minimumAllocation,
node.getAvailableResource())) {
attemptScheduling(node);
}
} catch (Throwable ex) { //这每次调度过程中如果发生异常,这个异常将被捕获,因此不会影响在其它节点上进行调度
//异常处理,略
}
}
}

long duration = getClock().getTime() - start;
fsOpDurations.addContinuousSchedulingRunDuration(duration);
}

比较器部分,实际上只是比较了内存

预留资源同非预留资源的区别对待

剥离预留/尝试分配资源

适合在这个节点运行

1
2
3
4
5
6
7
8
9
10
public enum NodeType {
NODE_LOCAL(0), //请求规定了必须运行在某个的服务器节点
RACK_LOCAL(1), //请求规定了必须运行在某个机架上
OFF_SWITCH(2); //这个请求对本地化没有要求
public int index;

private NodeType(int index) {
this.index = index;
}
}