LeaseRenewer源码浅析

LeaseRenewer源码浅析

根据https://issues.apache.org/jira/browse/HDFS-1870,找到了蛛丝马迹,LeaseRenewer在0.23.0版本前为DFSClient的内部类LeaseChecker;将LeaseChecker作为查找关键字,发现了更早的issue,即https://issues.apache.org/jira/browse/HADOOP-3169,该issue的发布版本为0.19.0,那么,就从0.18作为切入点。图1为0.18.3的源码

图1

首先可以看出来LeaseChecker是一个线程类,run()方法整体比较好理解:1s轮询一次调用namenode.renewLeaase(clientName)方法,clientName是DFSClient的实例变量,被final修饰,如图2:
在这里插入图片描述

图2

这说明一个DFSClient对象是跟一个clientName绑定的;同时,图2也可以看到DFSClient持有一个名为leaseChecker的Daemon类对象,结合图1LeaseChecker的源码以及图3中DFSClient的构造函数,可以看出,一个LeaseChecker对象跟一个DFSClient对象也是绑定的。

在这里插入图片描述

图3

这样子会引发两个问题:

  1. DFSClient可以理解为文件读、写的入口,但是租约——Lease只有在写操作时才会涉及,因此当一个DFSClient对象只用来进行读操作时,会浪费一个线程。
  2. 在一个JVM中,每一个DFSClient对象都需要一个LeaseChecker线程,这实际上有些浪费资源,多个DFSClient对象可以共用一个LeaseChecker线程。

针对#1,https://issues.apache.org/jira/browse/HADOOP-3169提出了解决思路,图4为0.19.0版本的代码

在这里插入图片描述

图4

主要有三个改动:

  1. DFSClient不再持有一个Daemon leaseChecker对象,而是改为持有一个LeaseChecker leasechecker对象;同时,DFSClient的构造函数不再负责调度leaseChecker.start(),而是推迟到DFSClient对象第一次进行写操作时。
  2. LeaseChecker类,增加了一个map用来缓存文件到输出流的映射关系。leaseChecker在周期性的执行renew()方法时,会进行判断,只有map非空时,才会真正的向NN发起RPC请求;当map为空时,调用renew()方法为空操作;
  3. LeaseChecker类,增加了一个Daemon对象和put()方法,这里需要提一句,put()方法是用synchronized进行修饰的,这个锁有两个用处:一是用来保护pendingCreates这个map;二是用来保护daemon。

至此,遗留了一个小问题:在LeaseChecker线程启动后,便无法停止,即便当前DFSClient对象已经不再进行写操作,所以https://issues.apache.org/jira/browse/HDFS-1840做了这个小优化,引入了一个int类型的currentId变量,当map从空变为非空状态时,currentId增1。在线程的run()方法中,循环退出条件为当前id值和currentId是否相等,如果不相等,退出循环,线程执行结束;如果map为空时,退出循环,线程执行结束。同时,为了防止DFSClient对象频繁的写操作(写操作耗时较短)导致频繁的restart leasechecker线程,新增了一个long类型的emptyTime变量,记录map为空后经过的时间,新增了一个long类型的gracePeriod变量,作为一个参照,含义为当map为空后经过gracePeriod时间后,才退出循环,从而结束线程。

这里有一个插曲,https://issues.apache.org/jira/browse/HDFS-1870开始,LeaseChecker类不再是DFSClient的内部类,改名为LeaseRenewer成为单独的一个类。

针对#2,https://issues.apache.org/jira/browse/HDFS-1865提出了解决思路,不同的DFSClient对象可以共用同一个LeaseRenewer对象。这里有一个很大的改动,担心自己无意中的文字加工,还是要截一下原文,如图5:

在这里插入图片描述
在这里插入图片描述

图5

虽然在一个JVM中可以存在多个DFSClient对象,但是在LeaseRenew层面,刻画客户端这个概念用DFSClient对象进行标识是不合理的,可以将使用同一用户(e.g. hive_user)访问同一Namenode(e.g. Active Namenode1)的DFSClient对象视为同一个客户端。代码改动为在LeaseRenewer中新增了Key这个静态内部类,用来标识客户端这一个概念,在LeaseRenewer类中新增了一个Key到LeaseRenewer的map,如图6:在这里插入图片描述

图6

其中,authority用来表示Namenode,UserGroupInformation用来表示用户。

至此,LeaseRenewer类成长为当前版本的雏形。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值