Hadoop3.2.1 【 HDFS 】源码分析 :FSDirectory类解析

Table of Contents

一.前言.

二.构造方法

三.常量

四.方法


一.前言.

Namenode最重要的两个功能之一就是维护整个文件系统的目录树(即命名空间namesystem) 。 HDFS文件系统的命名空间(namespace) , 也就是以“/”为根的整个目录树, 是通过FSDirectory类来管理的。 FSNamesystem也提供了管理目
录树结构的方法, 但FSNamesystem中的方法多是调用FSDirectory类的实现,FSNamesystem在FSDirectory类方法的基础上添加了editlog日志记录的功能。 而FSDirectory的操作则全部是在内存中进行的, 并不进行editlog的日志记录。

FSDirectory的设计使用了门面(Facade) 模式, 门面模式是指提供一个统一的接口去访问多个子系统的多个不同的接口, 它为子系统中的一组接口提供一个统一的高层接口, 使得子系统更容易使用

 

二.构造方法

序号参数默认值含义
1dfs.permissions.enabledtrue权限,默认开启
2dfs.permissions.superusergroupsupergroup超级用户组
3dfs.namenode.acls.enabledfalse设置为true以启用对HDFS ACL(访问控制列表)的支持。 默认情况下,禁用ACL。 禁用ACL时,NameNode拒绝与设置或获取ACL相关的所有RPC。
4dfs.ls.limit1000限制ls打印的文件数量。 如果小于或等于零,将最多打印DFS_LIST_LIMIT_DEFAULT(= 1000)。
5dfs.content-summary.limit5000一个锁定期内允许的最大内容摘要计数。 0或负数表示没有限制
6dfs.content-summary.sleep-microsec500在内容摘要计算中重新获得锁定之间的使线程进入睡眠状态的时间长度(以微秒为单位)
7dfs.namenode.fs-limits.max-component-length255定义路径的每个组件中以UTF-8编码的最大字节数。 值为0将禁用检查。
8dfs.namenode.fs-limits.max-directory-items1024 * 1024 ≈100 万

定义目录可以包含的最大项数。无法将属性设置为小于1或大于6400000的值。

9dfs.namenode.fs-limits.max-xattrs-per-inode32 
10final int MAX_DIR_ITEMS64 * 100 * 1000= 640万

我们需要一个最大最大值,因为默认情况下,
PB将message大小限制为64MB。
这意味着每个目录只能存储大约670万个条目,
但是为了安全起见,请使用640万个条目。

[ dfs.namenode.fs-limits.max-directory-items的最大值]

11dfs.namenode.name.cache.threshold10经常访问的文件的访问次数超过此阈值的次数被缓存在FSDirectory nameCache中。

 


  FSDirectory(FSNamesystem ns, Configuration conf) throws IOException {
    this.dirLock = new ReentrantReadWriteLock(true); // fair
    this.inodeId = new INodeId();
    rootDir = createRoot(ns);
    inodeMap = INodeMap.newInstance(rootDir);

    // 权限: 默认开启 ==> dfs.permissions.enabled : true
    this.isPermissionEnabled = conf.getBoolean(  DFSConfigKeys.DFS_PERMISSIONS_ENABLED_KEY, DFSConfigKeys.DFS_PERMISSIONS_ENABLED_DEFAULT);


    // dfs.permissions.ContentSummary.subAccess : false
    this.isPermissionContentSummarySubAccess = conf.getBoolean(
        DFSConfigKeys.DFS_PERMISSIONS_CONTENT_SUMMARY_SUBACCESS_KEY,
        DFSConfigKeys.DFS_PERMISSIONS_CONTENT_SUMMARY_SUBACCESS_DEFAULT);


    this.fsOwnerShortUserName =
      UserGroupInformation.getCurrentUser().getShortUserName();


    /// dfs.permissions.superusergroup  : supergroup
    this.supergroup = conf.get(
      DFSConfigKeys.DFS_PERMISSIONS_SUPERUSERGROUP_KEY,
      DFSConfigKeys.DFS_PERMISSIONS_SUPERUSERGROUP_DEFAULT);


    // dfs.namenode.acls.enabled : false
    this.aclsEnabled = conf.getBoolean(
        DFSConfigKeys.DFS_NAMENODE_ACLS_ENABLED_KEY,
        DFSConfigKeys.DFS_NAMENODE_ACLS_ENABLED_DEFAULT);


    LOG.info("ACLs enabled? " + aclsEnabled);
    this.posixAclInheritanceEnabled = conf.getBoolean(
        DFSConfigKeys.DFS_NAMENODE_POSIX_ACL_INHERITANCE_ENABLED_KEY,
        DFSConfigKeys.DFS_NAMENODE_POSIX_ACL_INHERITANCE_ENABLED_DEFAULT);
    LOG.info("POSIX ACL inheritance enabled? " + posixAclInheritanceEnabled);
    this.xattrsEnabled = conf.getBoolean(
        DFSConfigKeys.DFS_NAMENODE_XATTRS_ENABLED_KEY,
        DFSConfigKeys.DFS_NAMENODE_XATTRS_ENABLED_DEFAULT);
    LOG.info("XAttrs enabled? " + xattrsEnabled);
    this.xattrMaxSize = conf.getInt(
        DFSConfigKeys.DFS_NAMENODE_MAX_XATTR_SIZE_KEY,
        DFSConfigKeys.DFS_NAMENODE_MAX_XATTR_SIZE_DEFAULT);
    Preconditions.checkArgument(xattrMaxSize > 0,
        "The maximum size of an xattr should be > 0: (%s).",
        DFSConfigKeys.DFS_NAMENODE_MAX_XATTR_SIZE_KEY);
    Preconditions.checkArgument(xattrMaxSize <=
        DFSConfigKeys.DFS_NAMENODE_MAX_XATTR_SIZE_HARD_LIMIT,
        "The maximum size of an xattr should be <= maximum size"
        + " hard limit " + DFSConfigKeys.DFS_NAMENODE_MAX_XATTR_SIZE_HARD_LIMIT
        + ": (%s).", DFSConfigKeys.DFS_NAMENODE_MAX_XATTR_SIZE_KEY);

    this.accessTimePrecision = conf.getLong(
        DFS_NAMENODE_ACCESSTIME_PRECISION_KEY,
        DFS_NAMENODE_ACCESSTIME_PRECISION_DEFAULT);

    //dfs.storage.policy.enabled : true
    this.storagePolicyEnabled =
        conf.getBoolean(DFS_STORAGE_POLICY_ENABLED_KEY,
                        DFS_STORAGE_POLICY_ENABLED_DEFAULT);

    this.quotaByStorageTypeEnabled =
        conf.getBoolean(DFS_QUOTA_BY_STORAGETYPE_ENABLED_KEY,
                        DFS_QUOTA_BY_STORAGETYPE_ENABLED_DEFAULT);

    // dfs.ls.limit : 1000
    int configuredLimit = conf.getInt(
        DFSConfigKeys.DFS_LIST_LIMIT, DFSConfigKeys.DFS_LIST_LIMIT_DEFAULT);

    this.lsLimit = configuredLimit>0 ?
        configuredLimit : DFSConfigKeys.DFS_LIST_LIMIT_DEFAULT;

    // dfs.content-summary.limit : 5000
    this.contentCountLimit = conf.getInt(
        DFSConfigKeys.DFS_CONTENT_SUMMARY_LIMIT_KEY,
        DFSConfigKeys.DFS_CONTENT_SUMMARY_LIMIT_DEFAULT);

    //dfs.content-summary.sleep-microsec 500
    this.contentSleepMicroSec = conf.getLong(
        DFSConfigKeys.DFS_CONTENT_SUMMARY_SLEEP_MICROSEC_KEY,
        DFSConfigKeys.DFS_CONTENT_SUMMARY_SLEEP_MICROSEC_DEFAULT);
    
    // filesystem limits
    // 路径最大长度: dfs.namenode.fs-limits.max-component-length : 255
    this.maxComponentLength = conf.getInt(
        DFSConfigKeys.DFS_NAMENODE_MAX_COMPONENT_LENGTH_KEY,
        DFSConfigKeys.DFS_NAMENODE_MAX_COMPONENT_LENGTH_DEFAULT);

    // 目录最大数量 1024 * 1024 = 1048576  ≈ 100 万
    // dfs.namenode.fs-limits.max-directory-items :  1024 * 1024
    this.maxDirItems = conf.getInt(
        DFSConfigKeys.DFS_NAMENODE_MAX_DIRECTORY_ITEMS_KEY,
        DFSConfigKeys.DFS_NAMENODE_MAX_DIRECTORY_ITEMS_DEFAULT);


    // dfs.namenode.fs-limits.max-xattrs-per-inod: 32
    // inode的属性最大限制 32
    this.inodeXAttrsLimit = conf.getInt(
        DFSConfigKeys.DFS_NAMENODE_MAX_XATTRS_PER_INODE_KEY,
        DFSConfigKeys.DFS_NAMENODE_MAX_XATTRS_PER_INODE_DEFAULT);

    this.protectedDirectories = parseProtectedDirectories(conf);

    Preconditions.checkArgument(this.inodeXAttrsLimit >= 0,
        "Cannot set a negative limit on the number of xattrs per inode (%s).",
        DFSConfigKeys.DFS_NAMENODE_MAX_XATTRS_PER_INODE_KEY);

    // 我们需要一个最大最大值,因为默认情况下,
    // PB将message大小限制为64MB。
    // 这意味着每个目录只能存储大约670万个条目,
    // 但是为了安全起见,请使用640万个条目。

    // We need a maximum maximum because by default, PB limits message sizes
    // to 64MB. This means we can only store approximately 6.7 million entries
    // per directory, but let's use 6.4 million for some safety.
    final int MAX_DIR_ITEMS = 64 * 100 * 1000;
    Preconditions.checkArgument(
        maxDirItems > 0 && maxDirItems <= MAX_DIR_ITEMS, "Cannot set "
            + DFSConfigKeys.DFS_NAMENODE_MAX_DIRECTORY_ITEMS_KEY
            + " to a value less than 1 or greater than " + MAX_DIR_ITEMS);

    
    // dfs.namenode.name.cache.threshold: 10
    // 经常访问的文件的访问次数超过此阈值的次数被缓存在FSDirectory nameCache中。
    int threshold = conf.getInt(
        DFSConfigKeys.DFS_NAMENODE_NAME_CACHE_THRESHOLD_KEY,
        DFSConfigKeys.DFS_NAMENODE_NAME_CACHE_THRESHOLD_DEFAULT);
    NameNode.LOG.info("Caching file names occurring more than " + threshold
        + " times");
    
    nameCache = new NameCache<ByteArray>(threshold);
    namesystem = ns;
    this.editLog = ns.getEditLog();
    ezManager = new EncryptionZoneManager(this, conf);

    this.quotaInitThreads = conf.getInt(
        DFSConfigKeys.DFS_NAMENODE_QUOTA_INIT_THREADS_KEY,
        DFSConfigKeys.DFS_NAMENODE_QUOTA_INIT_THREADS_DEFAULT);

    initUsersToBypassExtProvider(conf);
  }

 

三.常量

■ INodeDirectory rootDir: 整个文件系统目录树的根节点, 是INodeDirectory类型的 。
■ FSNamesystem namesystem: Namenode的门面类, 这个类主要支持对数据块进行操作的一些方法, 例如addBlock()。
■ INodeMap inodeMap: 记录根目录下所有的INode,并维护INodeId ->INode的映射关系。
■ ReentrantReadWriteLock dirLock: 对目录树以及inodeMap字段操作的锁。
■ NameCache<ByteArray> nameCache: 将常用的name缓存下来, 以降低byte[]的使用, 并降低JVM heap的使用

 

四.方法

FSDirectory类中的方法相当多, 主要是封装了对文件系统目录树的操作, 例如增、删、 改、 查等。 基本上ClientProtocol中的方法, 都能在FSDirectory中找到对应的方法。

这个太多了就不罗列了,其实就是对目录层级权限的操作..

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值