从 50,000+ 个文件 NFS 挂载的目录中检索目录树的更好方法


A better way to retrieve a directory tree from a 50,000+ files NFS mounted directory

我被带到一个现有的CMS和文件管理Web应用程序上工作,该应用程序为商家提供了其在线网店的管理界面。管理应用程序是用PHP开发的。

当网站用户查看网店时,页面资产(主要是嵌套文件夹路径中的图像)直接从网店的HTML引用,并直接从独立于CMS系统的网络服务器提供。

但是为了列出/搜索/允许导航文件(即文件管理部分),CMS应用程序需要能够访问文件/文件夹目录结构。

因此,我们使用Linux NFS挂载从CMS服务器到文档文件服务器。如果任何特定商家的目录树中的文件数量不是太大(<10000),则这工作得很好。但是,某些商家在嵌套目录树中有超过 100000 个文件。走这个大小的树来获取目录结构可能需要 120 秒以上。

仅检索任何一个目录中的文件列表都非常快,但是当我们尝试识别这些"文件"中的哪些实际上是目录条目时,问题就来了,因此我们可以递归树。

似乎检查文件类型的 PHP 函数(在使用"readdir"或"scandir"检索的每个文件路径上调用"is_dir",或者使用带有标志GLOB_ONLYDIR的"glob")单独处理每个文件,而不是批量工作。因此,现在有 1000 个和 1000 个 NFS 命令正在发送。从我到目前为止的研究来看,这似乎是NFS的限制,而不是PHP的限制。

一个精简的类,仅显示有问题的函数:

class clImagesDocuments {
    public $dirArr;
    function getDirsRecursive( $dir ) {
        if ( !is_dir( $dir )) {
            return false;
        }
        if ( !isset( $this->dirArr )) {
            $this->dirArr = glob( $dir . "/*", GLOB_ONLYDIR );
        } else {
            $this->dirArr = array_merge( $this->dirArr, glob( $dir . "/*", GLOB_ONLYDIR ) );
            return false;
        }
        for( $i = 0; $i < sizeof( $this->dirArr ); $i ++) {
            $this->getDirsRecursive( $this->dirArr [$i] );
        }
        for( $i = 0; $i < sizeof( $this->dirArr ); $i ++) {
            $indexArr = explode( $dir, $this->dirArr [$i] );
            $tempDir[$indexArr[1]] = $this->dirArr [$i];
        }
        $this->dirArr = $tempDir;
    }
}

在文件文档服务器上本地执行相同的PHP代码以检索目录树等要快得多(2或3个数量级),可能是因为本地文件系统正在缓存目录结构。 我被迫认为我的问题是由于 NFS。

我正在考虑编写一个简单的 Web 应用程序,它将在文件文档 Web 服务器上运行,并通过 API 提供目录结构的实时查找。

我将不胜感激任何想法或建议。

另一种解决方案 - 您可以在所有目录前面加上一些字符串,当您获得包含文件的列表时,您可以通过检查它们是否包含字符串来检查哪些实际上是目录。您可以通过这种方式完全避免is_dir()

老问题,但对我来说是当前的问题。

一个解决方案:

在您的服务器上更好的

存储服务器上(要快得多)在每个目录上运行带有-X(XML输出)的树 https://linux.die.net/man/1/tree,或者在顶部目录上运行一次,并将输出发送到".dirStructure.xml"文件(开头带有.,因此您可以从列表中忽略它)

例如。树 -x -f -q -s -D —目录 -X

然后让你的脚本加载这个结构,并使用它来显示树结构。您可以为每个商家或一个全局商家制作此文件,只需遍历它即可找到商家。

您可以通过每分钟一次的 cron 运行它,也可以创建和 API 调用在存储计算机上运行它。

您可以在更改文件时更新此 xml。

无需数据库。

您还可以监视对存储端目录的更改,并在每次发生更改时重新创建 xml。 https://superuser.com/questions/181517

编辑:如何监视完整的目录树以了解 Linux 中的更改?