zoukankan      html  css  js  c++  java
  • YARN的约束化标签支持

    前言


    在比较早期的时候,YARN就已经实现了具有分片功能的node label功能,以此确保应用资源的使用隔离。我们可以理解为这种标签是单一维度的,假设我们有多维度标签使用的需求时,这种node label就不是那么好用了。当然,你可以说,我们可以构建多个标签,一个节点同时赋予多个维度标签,但是其实这同样不会那么好操作。今天笔者要阐述的就是YARN node label特性的升级版特性:Constraint nodel label(约束化标签)。简单的理解,我们可以把它理解为是一种个性化标签。

    Constraint node label


    约束化标签相较于原本标签功能,它的灵活性大大提升了。

    首先,它是支持多维度,多类型标签。比如标签可以是boolean型,int型或者string型。定义多个标签类型是为了可以表示不同的维度含义,比如我们可以用boolean类型的标签来表示某节点是否是期待的操作系统类型,比如!Windows的含义就是当前的操作系统不是Windows系统。int类型的我们可以表示节点磁盘数量信息等。通过上述多类型的标签表示,可以精确具体地描述出一个节点的特征。

    第二点,基于多维度标签的表达式匹配。因为约束化标签是支持多类型的,对应条件匹配模式当然也不仅仅是只有int或not in这样的关系。它还可以支持如下的条件操作原语文

    1.包含关系判断: in, not in
    2.值大小判断:<,>,>=,=,<=
    3.条件运算操作关系:&&,//

    通过以上3种条件的拼接组合,我们可以组合出非常灵活的条件判断规则,比如下面这个例子:NUM_DISK > 3 && !WINDOWS上述条件表示的含义是节点需要同时满足磁盘数大于3并且操作系统不是WINDOWS系统2个特征。这个表达式很好的体现了约束化标签中“约束”的含义。基于多维度的特征定义和条件过滤,用户可以做出更精确的标签识别。

    约束化标签实现原理


    下面我们来了解约束化标签的具体实现。在代码实现层面,我们如何来设计并实现约束化标签的功能呢?

    要实现这个功能,我们首先要明确与约束化标签相关的一些概念,然后定义出相应类以及内部方法。以下是目前YRAN约束化标签对此的具体设计。

    第一个,约束值类,主要包含实际值以及比较操作值,比如long类型的约束值类定义如下:

      static class LongConstraintValue implements ConstraintValue {
        // 标签值
        private long value = 0;
        // 与外部值的比较操作运算符
        private ExpressionCompareOp compareOp;
    
        ...
    
        /**
         * 与外部值的比较方法
         */
        @Override
        public boolean matches(ConstraintValue targetValue) {
          assert (targetValue instanceof LongConstraintValue);
          double nodeConstraintVal = ((LongConstraintValue) targetValue).value;
          // 根据具体操作符做值的比较
          switch (compareOp) {
          case EQUAL:
            return value == nodeConstraintVal;
          case NOT_EQUAL:
            return value != nodeConstraintVal;
          case GREATER_OR_EQUAL:
            return nodeConstraintVal >= value;
          case GREATER_THAN:
            return nodeConstraintVal > value;
          case LESS_THAN:
            return nodeConstraintVal < value;
          case LESS_OR_EQUAL:
            return nodeConstraintVal <= value;
          default:
            return false;
          }
        }

    当然,对于string类型,就是EQUAL和NOT_EQUAL类型的。

    第二个,操作符类型,就是代码里里提到的,目前总共我们会涉及到以下可能用到的操作符语义。

    public enum ExpressionCompareOp {
      LESS_THAN, // '<' or 'lt'
      LESS_OR_EQUAL, // '<=' or 'le'
      EQUAL, // '==' or 'eq'
      NOT_EQUAL, // '!=' or 'ne' or 'ene' (for exists but not equal)
      GREATER_OR_EQUAL, // '>=' or 'ge'
      GREATER_THAN, // '>' or 'gt'
      IN, // 'in'
      NOT_IN, // 'not_in'
      EXISTS, // no operand only if the name is specified
      NOT_EXISTS, // '! <constrainName>'
    }

    第三个,约束比较类型,我们可以理解为它是一个策略类,它定义了不同类型值进行比较的方式,根据输入不同的比较原语操作符。下面是此类的接口定义:

    /**
     * 定义了值进行比较的方式,根据输入不同的比较原语操作.
     */
    public interface ConstraintType {
      /**
       * 类型名
       */
      String getConstraintTypeName();
    
      /**
       * 支持的操作原语
       */
      Set<ExpressionCompareOp> getSupportedCompareOperation();
    
      /**
       * 根据输入操作原语,返回具体约束值类
       */
      ConstraintValue getConstraintValue(ExpressionCompareOp compareOp)
          throws YarnException;
    }

    我们来看其中的一个具体子类,

    public class LongConstraintType implements ConstraintType {
      // 此类型策略可支持的所以操作符
      private Set<ExpressionCompareOp> supportedOps =
          new HashSet<>(Arrays.asList(ExpressionCompareOp.values()));
    
      @Override
      public String getConstraintTypeName() {
        return ConstraintsUtil.LONG_CONSTRAINT_TYPE;
      }
    
      @Override
      public Set<ExpressionCompareOp> getSupportedCompareOperation() {
        return supportedOps;
      }
    
      @Override
      public ConstraintValue getConstraintValue(ExpressionCompareOp compareOp) {
        // 根据比较操作符,返回不同的约束值类,然后约束值里再进行具体的比较操作
        switch (compareOp) {
        case IN:
          return new LongSetConstraintValue(true);
        case NOT_IN:
          return new LongSetConstraintValue(true);
        default:
          return new LongConstraintValue(compareOp);
        }
      }

    第四点,约束特征表达式,约束特征表达式可以理解为就是一条完整的表达式条件,它包括了各个子条件约束值实例,以及连接运算表达式(与,或关系),如下:

    public class ConstraintExpressionList extends ConstraintExpression {
    
      /**
       * 操作运算符,与,或操作
       */
      @Private
      @Unstable
      public static enum Operator {
        AND, OR
      }
    
      private Operator operator;
      // 包含的子表达式,因为可能存在嵌套的条件判断
      private List<ConstraintExpression> expressionList =
          new ArrayList<ConstraintExpression>();
    
      public ConstraintExpressionList(ConstraintExpression... expressions) {
        this(Operator.AND, expressions);
      }
    
      public ConstraintExpressionList(Operator op,
          ConstraintExpression... expressions) {
        this.operator = op;
        this.expressionList =
            new ArrayList<ConstraintExpression>(Arrays.asList(expressions));
      }
    
      ...
    
      /**
       * 条件匹配判断
       */
      @Override
      public boolean evaluate(Map<String, ConstraintValue> nodeConstraintMappings) {
        for (ConstraintExpression constraintExpression : expressionList) {
          if (constraintExpression.evaluate(nodeConstraintMappings)) {
            // 操作符如果是或关系,有表达式判断成立即为成功
            if (operator == Operator.OR) {
              return true;
            }
          } else if (operator == Operator.AND) {
            // 操作符如果是与关系,有表达式判断不匹配即为成功
            return false;
          }
        }
        // 没有条件判断,直接比操作符
        return (operator == Operator.AND);
      }

    因为在表达式中,存在嵌套条件的可能,所以这里表达式有以下2两类:

    • LIST列表类型,LIST类型表达式里面可能存在子列表型或者COMPARE型。
    • COMPARE操作比较型。

    比如下面这个表达式,就是LIST类型和COMPARE表达式的组合。

    (NUM_DISK >= 3 && !WINDOWS) || JDK_VERSION >= 1.8

    上述表达式,可以看做一个大LIST类型表达式 = (小LIST表达式(2个COMPARE表达式组成))+ COMPARE表达式。

    所以在表达式定义这块,最为复杂和重要的其实是表达式的解析这块。由于篇幅有限,笔者这里就不展开具体阐述了,解析类代码已上传至文章末尾的链接处,感兴趣的同学可以深入继续深入了解了解,主要的一个思路方向是借助于堆栈结构,从左往右解析约束表达式字符串。

    利用以上3大类型定义,就能构造出非常灵活的标签描述以及特征表达式的判断了。
    基于这些表达式的判断,RM可以做约束标签的节点筛选和过滤 ,后续的Container分配过程与普通node label的过程基本一致。

    引用


    [1].https://issues.apache.org/jira/browse/YARN-3409. Support Node Attribute functionality
    [2].https://issues.apache.org/jira/secure/attachment/12937633/Node-Attributes-Requirements-Design-doc_v2.pdf
    [3].https://github.com/linyiqun/hadoop-yarn/tree/master/ConstraintNodeLabel

  • 相关阅读:
    [转载]iOS 开发中为什么更新UI都要放在主线程中?
    GCD小结
    多线程的实现
    图片缓存、PathForResource、NSBundle
    IOS全路径和文件名方法、NSBundle
    plist文件
    iphone区别翻新机
    iPhone4S国行、港版、美版、妖机识别与选购(转)
    应用沙盒
    IOS实现新特性功能
  • 原文地址:https://www.cnblogs.com/bianqi/p/12183599.html
Copyright © 2011-2022 走看看