zoukankan      html  css  js  c++  java
  • HDFS RBF的资源隔离设计

    前言


    Hadoop社区在HDFS-10467中实现了基于路由的federation功能,此功能比原先传统的HDFS federation+viewfs的方式有了很大的改进,真正做到了基于后端的路由映射,而不是viewfs在客户端做地址解析转发。基于后端来做的话,背后的mount映射管理权就归到了系统管理员身上了。更重要的一点,当想要更换mount信息时,无需向所有客户端推送更新的mapping文件,而是通过简单的管理员命令操作RBF mount table信息即可。形象地比喻,RBF中的Router是架在下游NN和面向Client的一个中间角色。在这套模式下,Router就成了一个关键角色,它的响应快慢将影响到所有Client的请求访问。但这里的Router并不是足够稳定的,比如下游NN响应变慢,进而会反压到Router(Router共用了一个thread pool做调用执行的)。这样其它正常NN的请求就会被block住,于是这里就会有潜在的资源隔离的问题。本文笔者来简单聊聊社区目前对此的一个方案设计,主要原理是通过在Router Client层面对其做fairness的管控,和目前Hadoop的Fair Callqueue还是不太一样的。

    RBF的资源隔离和FCQ的资源隔离


    当我们经常在说资源isolation的时候,我们免不了会提到fairness的问题。因为没有做到很好的isolation,fairness无法得到保证,而FCQ(Fair Callqueue)就做了这样一个事情。但是注意的是,这里的fairness指的不是绝对意义上的公平,只能说是相对公平,一种按照我们给定的某种程度的公平。

    但是FCQ和RBF的资源隔离的问题类型还是有所不同的。FCQ面向的是单一集群内的用户间的影响问题,而RBF里,这个所谓的“用户”则变成了各个cluster的NN。还有在FCQ中,我们可以拿到用户请求的详细信息,而在RBF里,我们只能拿到最基本的NN的信息。

    下面我们来了解一下FCQ的原理模型图:

    在这里插入图片描述
    目前FCQ的fairness策略已经是比较智能化了,包括有根据请求频率定义优先级,然后根据优先级定义权重,最后进行加权轮询调度处理。在每次的iteration内,每类请求能够保证被得到处理。

    相对于FCQ面向用户层面比较细粒度的控制,RBF的fairness管控在初期实现只要做到对每个cluster的请求permit控制即可。比方说,在单位时间内,我允许Router向A cluster分派6个请求,而B cluster只允许处理4个请求。通过限制允许请求数来避免下游NN overload导致Router处理变慢的情况。

    以下是一个RBF fairness的预想效果图,

    在这里插入图片描述

    通过RBF fairness manager的介入,handler在逻辑层面被按比例地划分给不同的namespace,注意笔者在这里指的是逻辑层面,不是真的RBF修改了NN Server里的handler处理。

    RBF的fairness管控原理


    下面笔者来简单聊聊RBF的fairness管控原理。Fairness管控是在Router这个服务里做的,更具体地来说是在Router Client层面做的,这里的Router Client可理解为是Router请求转向实际NN的一个Proxy。

    在社区的实现方案中,引入了FairManager的对象,FairManager里包含了fairness的控制策略。目前的一个默认策略是通过为每个namespace设置一个信号量对象Semaphore,来进行请求的限制,相关代码如下:

    +  /** Hash table to hold semaphore for each configured name service. */
    +  private Map<String, Semaphore> permits;
    

    初始化的时候,通过读取配置中为每个ns指定的permit数,进行Semaphore的设定。

      @Override
      public void assignHandlersToNameservices(Configuration conf) {
      ...
     for (String namenode : namenodes) {
          String[] namenodeSplit = namenode.split("\.");
          String nsId = null;
          if (namenodeSplit.length == 2) {
            nsId = namenodeSplit[0];
          } else if (namenodeSplit.length == 1) {
            nsId = namenode;
          } else {
            String errorMsg = "Wrong name service specified :" +
                Arrays.toString(namenodeSplit);
            LOG.error(errorMsg);
            throw new PermitAllocationException(
                errorMsg);
          }
          if (nsId != null) {
            int dedicatedHandlers =
                conf.getInt(DFS_ROUTER_FAIR_HANDLER_COUNT_KEY_PREFIX + nsId, 0);
            LOG.info("Dedicated handlers {} for ns {} ", dedicatedHandlers, nsId);
            if (dedicatedHandlers > 0) {
              if (!this.permits.containsKey(nsId)) {
                handlerCount -= dedicatedHandlers;
                // Total handlers should not be less than sum of dedicated
                // handlers.
                validateCount(handlerCount, 0);
                this.permits.put(nsId, new Semaphore(dedicatedHandlers));
                logAssignment(nsId, dedicatedHandlers);
              }
            } else {
              unassignedNS.add(nsId);
            }
          }
     }
    

    当客户端请求调用时,fairness policy会在对应的ns的Semaphore中进行permit的acquire操作,如果获取不到意为当时针对此ns的请求资源未被完全释放,抛Exception异常。这个行为就做到完美想要的资源控制的效果,简接达到Router内的isolation的目的。

    @Override
      public void acquirePermit(String nsId) throws NoPermitAvailableException {
        if (!this.permits.get(nsId).tryAcquire()) {
          throw new NoPermitAvailableException(nsId);
        }
      }
    
      @Override
      public void releasePermit(String nsId) {
        this.permits.get(nsId).release();
      }
    

    请求调用完成后,调用releasePermit方法。一个Sample call如下:

    public Object invokeSingle(final String nsId, RemoteMethod method)
         UserGroupInformation ugi = RouterRpcServer.getRemoteUser();
         List<? extends FederationNamenodeContext> nns =
             getNamenodesForNameservice(nsId);
        acquirePermit(nsId, ugi, method.getMethod());
        try {
          RemoteLocationContext loc = new RemoteLocation(nsId, "/", "/");
          Class<?> proto = method.getProtocol();
          Method m = method.getMethod();
          Object[] params = method.getParams(loc);
          return invokeMethod(ugi, nns, proto, m, params);
        } finally {
          releasePermit(nsId, ugi, method.getMethod());
        }
    }
    

    RBF的fairness管控原理流程图如下所示:

    在这里插入图片描述

    当然目前RBF初期fairness的控制策略相比于FCQ来说,它主要通过的预先定义配置的方式做的控制,缺乏了些灵活性。后续的改进可以从动态调整permit值这个方向做改进,并实现新的policy。

    引用


    [1].https://issues.apache.org/jira/browse/HDFS-14090 . RBF: Improved isolation for downstream name nodes

  • 相关阅读:
    Nodejs 开发指南 Nodejs+Express+ejs 开发microblog开发心得
    转载 java学习注意点
    STM32f103的数电采集电路的ADC多通道采集程序
    时间复杂度与空间复杂度
    RS232串口通信详解
    实现扫码登录
    TCP/UDP区别与联系
    Tcp三次握手/四次挥手
    浅谈CSRF攻击方式
    图片淡入淡出
  • 原文地址:https://www.cnblogs.com/bianqi/p/12183535.html
Copyright © 2011-2022 走看看