源码分析Ambari的DAG是如何做的

来源:互联网 发布:fluent分析软件 编辑:程序博客网 时间:2024/05/20 14:17

我认为Ambari最有趣的地方之一是如何计算DAG(Directed acyclic graph,有向无环图)

简述

先简要概括一下Ambari是如何确定执行流程的:

ambari server会根据集群的元数据信息,在执行某一个Operation时候建立一个Stage DAG,根据这个DAG,划分不同的Stage,Stage间有执行顺序关系,必须按着顺序来;再根据每一个Stage,生成Command的DAG,将Command下发给ambari agent执行,第一个Stage的所有Command全部执行成功,才会执行第二个Stage,依次类推。


相关的类

当然,有很多细节需要补充,我们先认识几个类,按理解的重要性排序:

RoleGraphNode

第一个类:RoleGraphNode,它可以看成DAG的一个点

public class RoleGraphNode {  public RoleGraphNode(Role role, RoleCommand command) {    this.role = role;    this.command = command;  }  private Role role;  private RoleCommand command;  private int inDegree = 0;  private List<String> hosts = new ArrayList<String>();  private Map<String, RoleGraphNode> edges = new TreeMap<String, RoleGraphNode>();  public synchronized void addHost(String host) {    hosts.add(host);  }  public synchronized void addEdge(RoleGraphNode rgn) {    if (edges.containsKey(rgn.getRole().toString())) {      return;    }    edges.put(rgn.getRole().toString(), rgn);    rgn.incrementInDegree();  }  private synchronized void incrementInDegree() {    inDegree ++;  }  public Role getRole() {    return role;  }  public RoleCommand getCommand() {    return command;  }  public List<String> getHosts() {    return hosts;  }  public int getInDegree() {    return inDegree;  }  Collection<RoleGraphNode> getEdges() {    return edges.values();  }  public synchronized void decrementInDegree() {    inDegree --;  }  @Override  public String toString() {    StringBuilder builder = new StringBuilder();    builder.append("("+role+", "+command +", "+inDegree+")");    return builder.toString();  }}
  • 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
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

一个DAG的节点有两部分构成,Role和RoleCommand,

(1) Role: Role defines the components that are available to Ambari. 说白了,就是component。(2) RoleCommand:一个枚举类,包含:INSTALL,UNINSTALL,START,STOP,EXECUTE,ABORT,UPGRADE,SERVICE_CHECK,  /**   * Represents any custom command   */  CUSTOM_COMMAND,  /**   * Represents any action   */  ACTIONEXECUTE
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

前面提到,Stage需要按顺序执行,那DAG如何确定顺序呢?

数据结构课都有上过,既然是一个有向无环图,那么先找到所有入度为0的nodes,这些nodes可以被划分在第一个Stage中,然后去掉这些nodes,以这些nodes为起点的边的终点的nodes的入度要-1,再找到所有入度为0的nodes,那么这些nodes可以被划分为第二个Stage,依次类推,就可以确定有多少个Stage和各个Stage的执行顺序。

在代码中是如何体现的呢?

每个RoleGraphNode都可以表示为一个(role, command, inDegree)三元组,比如(datanode, install, 0); 
每个RoleGraphNode都有该节点的边的信息(Map

RoleCommandOrder

第二个类:RoleCommandOrder,它可以理解成是如何生成DAG的graph的规则:

This class is used to establish the order between two roles.
  • 1

判定规则函数实现如下:

  /**   * Returns the dependency order. -1 => rgn1 before rgn2, 0 => they can be   * parallel 1 => rgn2 before rgn1   *    * @param rgn1 roleGraphNode1   * @param rgn2 roleGraphNode2   */  public int order(RoleGraphNode rgn1, RoleGraphNode rgn2) {    RoleCommandPair rcp1 = new RoleCommandPair(rgn1.getRole(),        rgn1.getCommand());    RoleCommandPair rcp2 = new RoleCommandPair(rgn2.getRole(),        rgn2.getCommand());    if ((this.dependencies.get(rcp1) != null)        && (this.dependencies.get(rcp1).contains(rcp2))) {      return 1;    } else if ((this.dependencies.get(rcp2) != null)        && (this.dependencies.get(rcp2).contains(rcp1))) {      return -1;    } else if (!rgn2.getCommand().equals(rgn1.getCommand())) {      return compareCommands(rgn1, rgn2);    }    return 0;  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

给定两个node:node1和node2 
1. 如果node1 -> node2,则返回-1; 
2. 如果node1和node2不存在先后关系,则返回0; 
3. 反之,如果node2 -> node1,则返回1;

谁先谁后是根据command的类型决定: 
INSTALL -> START -> EXECUTE -> SERVICE_CHECK -> STOP

  private int compareCommands(RoleGraphNode rgn1, RoleGraphNode rgn2) {    // TODO: add proper order comparison support for RoleCommand.ACTIONEXECUTE    RoleCommand rc1 = rgn1.getCommand();    RoleCommand rc2 = rgn2.getCommand();    if (rc1.equals(rc2)) {      //If its coming here means roles have no dependencies.      return 0;    }    if (independentCommands.contains(rc1) && independentCommands.contains(rc2)) {      return 0;    }    if (rc1.equals(RoleCommand.INSTALL)) {      return -1;    } else if (rc2.equals(RoleCommand.INSTALL)) {      return 1;    } else if (rc1.equals(RoleCommand.START) || rc1.equals(RoleCommand.EXECUTE)            || rc1.equals(RoleCommand.SERVICE_CHECK)) {      return -1;    } else if (rc2.equals(RoleCommand.START) || rc2.equals(RoleCommand.EXECUTE)            || rc2.equals(RoleCommand.SERVICE_CHECK)) {      return 1;    } else if (rc1.equals(RoleCommand.STOP)) {      return -1;    } else if (rc2.equals(RoleCommand.STOP)) {      return 1;    }    return 0;  }
  • 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
  • 29
  • 30
  • 31

这里要明确的是: 
除了上面的规则,还有一类规则信息是config,比如有role_command_order.json这个配置文件给定的规则,这类规则通常规定了不同component之间的顺序关系,可以是一个service间的不同component,比如:

"HIVE_SERVER-START": [  "HIVE_METADATA_DATABASE-START"],
  • 1
  • 2
  • 3

也可以是不同service间的不同component,比如:

"KAFKA_MANAGER-START": [  "ZOOKEEPER_SERVER-START"],
  • 1
  • 2
  • 3

再比如有service的metainfo.xml这个配置文件给定的规则,规定了service间的依赖关系:

<requiredServices>    <service>YARN</service>    <service>HIVE</service>    <service>HDFS</service></requiredServices>
  • 1
  • 2
  • 3
  • 4
  • 5


RoleGraph

第三个类:RoleGraph,通过给定的nodes来划分Stage,提供了如下方法:

(1) public void build(Stage stage)给定一个Stage,建立一个DAG(2) public List<Stage> getStages()给定nodes,建立Stages(3) private synchronized void removeZeroInDegreeNode(String role)去除入度为0的node(4) private Stage getStageFromGraphNodes(Stage origStage,      List<RoleGraphNode> stageGraphNodes)给定一个Stage,和一些nodes,重建一个新的Stage(5) public String stringifyGraph()字符串表示DAG
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

这里要明确的是:有两种DAG 
1. Stage间的DAG:根据nodes建立Stage DAG,即不同Stage的DAG; 
2. Stage内部的DAG:根据给定Stage内部的nodes建立Task DAG,即不同Command的DAG;

阅读全文
0 0
原创粉丝点击