我被带到一个现有的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 中的更改?