记录一次HDFS RPC返回Response过程慢导致的性能问题

本文探讨了HDFS NameNode在处理RPC请求时遇到的性能问题,特别是在Handler处理RPC响应阶段的延迟。在开启安全模式的集群环境中,加密响应信息成为性能瓶颈。通过使用async-profile进行性能分析,发现了Handler在返回response阶段的延误。为了解决这个问题,提出了两种可能的解决方案:优化加密算法或实现RPC响应的异步处理。文中详细介绍了如何仿照async editlog的处理方式,对RPC call进行异步响应改造,并提供了核心代码改动。虽然测试集群内已成功运行,但生产环境的效果还有待验证。
摘要由CSDN通过智能技术生成

前言


众所周知,在HDFS NameNode中,一直都有一个老生常谈的难题就是其扩展性的问题,而很多时候我们说HDFS的扩展性问题时我们很多时候都在谈的点在于里面全局锁的问题。一个很通常的场景是NameNode在高并发请求处理下存在着激烈的锁竞争,进而使得用户感觉到他们的请求被处理的有点慢。不过本文笔者不聊关于全局锁优化的问题,最近笔者遇到了另外一种NameNode性能慢的场景,这个事情是发生在锁外的,发生的场景也比较有意思,于是借此机会简单聊聊。

NameNode请求处理慢的场景


我们先来探讨几个能够引发NameNode请求处理慢的场景?

  • NameNode处于严重Full GC阶段
  • NameNode锁竞争激烈
  • NameNode内部用于处理用户请求的Handler持续处于繁忙状态

上述3点是笔者能够快速联想到的场景,除去第一点是JVM层面的优化后,后面两点其实不太好优化,后面两点很多时候是和集群所面临的请求吞吐量有关联。有人可能会说了,上面第三点关于Handler繁忙的状态,我们不可用简单调大NameNode Handler count数量不就可用解决了嘛。调大Handler表面上能够增大throughput,但是这还意味着一个问题:在同一个时间,NameNode内部会有更为激烈的锁竞争问题。锁竞争意味着就会有锁等待。

所以针对上面Handler繁忙的问题,应该从以下几点切入点入手:

Handler为什么处于繁忙状态?Handler在处理 RPC call的某个阶段慢了?是因为在等锁所以导致Handler处理慢?

OK,下面笔者来好好聊聊笔者遇到的Handler处理慢的问题。

RPC返回response的Handler处理慢问题


在笔者遇到的生产场景中,时不时就会出现NameNode callqueue满的情况,但是它的process time其实并没有显示出特别慢的迹象。在最一开始,笔者也是自然怀疑的是NameNode锁的问题,后来经过了一系列的锁局部优化后,还是偶尔会遇到NameNode慢的问题。

这个时候,我们采用了一样profile利器:async-profile,来帮助我们一探究竟。

于是我们发现了一段开销较高的doResponse阶段,
在这里插入图片描述
从上图中,我们果然捕捉到了Handler的run方法处理阶段,然后我们再点击进入里面详细的堆栈信息方法,如下图所示:
在这里插入图片描述

从上图中,我们可以得到许多有用的信息点:

  • Handler慢发生在返回response的操作里面,这个阶段已经是在锁外了,在RPC处理完毕之后了已经。
  • Response返回操作里面又是主要花在了加密返回信息内容的步骤上。

这里需要说下背景,笔者的这个集群环境是开启了Security模式的,所以会有response加密的过程。一般集群如果没有开启安全认证这些的话,这步骤估计是没有的。

OK,找到了问题的根源后,我们立马想到了下面两项action:

  • 第一点,是否有可能改进或替换现有的response加密算法,提升其加密效率。
  • 第二点,是否能够将返回response阶段进行异步处理,不去阻塞Handler的处理。

鉴于第一种方法涉及到加密算法的改动,risk比较高,因此我们先考虑采用第二点的方法。还有一点是,第二点提到的特性在实际代码中已经可以支持,async editlog就是用了Hadoop RPC Server底层这个异步response特性来做的。现在的问题其实是如何让正常RPC call处理也能走异步response的方式,目前的HDFS RPC response返回都是同步的。

HDFS RPC call异步response改造


接下来,笔者仿照async editlog的处理方式,对局部RPC call进行了试验改造。

以下是相关核心代码的改动,主要仿照了HDFS-9198 IBR异步线程处理加上HADOOP-10300 RPC call postpone的处理逻辑。

首先定义好postpone线程专门处理这样的延时response call,

  /**
   * The flag that if we should skip the handle by PostponeRpcCallThread.
   * This is only used for testing.
   */
  @VisibleForTesting
  static boolean SKIP_POSTPONE_HANDLE = false;
  /**
   * Whether to enable async rpc call response. If we enabled this feature,
   * the rpc call response will be postponed return to client side.
   */
  private boolean asyncResponse;

  /**
   * The thread specified for dealing with postponed rpc calls.
   */
  private PostponeRpcCallQueueProcessingThread postponeRpcCallThread;

然后在这个线程内,会设置一个队里来存放需要延时返回response call的队列,外加一个加call进队列的方法和处理队列的方法操作。

 /**
   * The thread specified for dealing with postponed rpc calls.
   */
  private class PostponeRpcCallQueueProcessingThread extends Thread {
   
    private final BlockingQueue<Server.Call> postponeRpcCallqueue =
        new ArrayBlockingQueue<>(1024);

    private static final long MAX_LOCK_HOLD_MS = 4;
    private long lastFullTime = 0;

    PostponeRpcCallQueueProcessingThread() {
   
      super("Postpone Rpc call processor");
      setDaemon(true);
    }

    @Override
    public void run() {
   
      try {
   
        processQueue();
      } catch (Throwable t) {
   
        ExitUtil.terminate(1, getName() +
            " encountered fatal exception: " + t);
      }
    }
    
	,,,
	
	/**
     * Insert rpc call to be postponed response.
     * @param call
     * @throws InterruptedException
     */
    private void enqueue(Server.Call call) throws InterruptedException {
   
      if (!postponeRpcCallqueue.offer(call)) {
   
        long now = Time.monotonicNow();
        if (now - lastFullTime > 4000) {
   
          lastFullTime = now;
          LOG.info("Postpone rpc call queue is full.");
        }
        postponeRpcCallqueue.put(call);
      }
    }
}

接下来我们看看这里NameNode如何加入RPC call进队列,笔者这里取了getBlockLocations这个call做为测试,

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值