[英]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.