[英]A better way to retrieve a directory tree from a 50,000+ files NFS mounted directory
我被带去开发现有的 CMS 和文件管理 Web 应用程序,该应用程序为商家提供了用于其在线网上商店的管理界面。 管理应用程序是用 PHP 开发的。
当网站用户查看网店时,页面资产(主要是嵌套文件夹路径中的图像)直接从网店的 HTML 中引用,并直接从独立于 CMS 系统的 Web 服务器提供服务。
但是为了列出/搜索/允许导航文件(即文件管理部分),CMS 应用程序需要能够访问文件/文件夹目录结构。
所以我们使用 Linux NFS 从 CMS 服务器挂载到文档文件服务器。 如果任何特定商家的目录树中的文件数量不是太大(<10000),这将非常有效。 然而,一些商家的嵌套目录树中有超过 100000 个文件。 遍历这种大小的树以获取目录结构可能需要 120 多秒。
只检索任何一个目录中的文件列表是相当快的,但是当我们试图识别这些“文件”中的哪些实际上是目录条目时,问题就出现了,因此我们可以向下递归树。
似乎用于检查文件类型的 PHP 函数(在使用“readdir”或“scandir”检索的每个文件路径上调用“is_dir”,或使用带有标志 GLOB_ONLYDIR 的“glob”)单独对每个文件起作用,而不是批量处理。 所以现在有成千上万的 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。
我正在考虑编写一个简单的 webapp,它将在文件文档 web 服务器上运行,并通过 API 提供目录结构的实时查找。
我很感激任何想法或建议。
另一种解决方案 - 您可以用一些字符串作为所有目录的前缀,当您获得包含文件的列表时,您可以通过检查它们是否包含字符串来检查哪些实际上是目录。 您可以完全避免使用is_dir()
这样。
老问题,但对我来说是当前的问题。
一种解决方案:
在存储服务器上更好的服务器上(快得多)在每个目录上或在顶级目录上运行带有 -X(XML 输出)的 tree https://linux.die.net/man/1/tree并发送输出到“.dirStructure.xml”文件(以.开头,这样你就可以从列表中忽略它)
例如。 树 -x -f -q -s -D —dirfirst -X
然后让你的脚本加载这个结构并使用它来显示树结构。 您可以为每个商家或一个全球商家制作此文件,然后遍历它以查找商家。
你可以每分钟通过 cron 运行它,或者创建和 API 来调用在存储机器上运行它。
您可以在更改文件时更新此 xml。
不需要数据库。
您还可以监视存储端目录的更改,并在每次更改时重新创建 xml。 https://superuser.com/questions/181517
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.