2015-03-13 35 views
2

我被引入到現有的CMS和文件管理Web應用程序中,該應用程序爲商家提供其在線網上商店的管理界面。管理應用程序是用PHP開發的。從50,000多個文件中檢索目錄樹的更好方法NFS掛載的目錄

當網站用戶正在查看網上商店時,網頁資產(主要是嵌套文件夾路徑中的圖像)直接從網上商店的HTML引用,並直接從與CMS系統分離的網絡服務器提供。

但是爲了列出/搜索/允許導航文件(即文件管理部分),CMS應用程序需要能夠訪問文件/文件夾目錄結構。

因此,我們使用Linux NFS掛接到CMS服務器的文檔文件服務器。如果任何特定商家的目錄樹中的文件數量不是太大(< 10000),則此方法效果相當好。但是,某些商家的嵌套目錄樹中有超過100000個文件。走這個大小的樹來獲取目錄結構可能需要超過120秒。

檢索任意一個目錄中的文件列表非常快,但是當我們嘗試確定哪些「文件」實際上是目錄條目時,問題就出現了,因此我們可以對該樹進行遞歸處理。

看來,PHP函數檢查文件類型(在每個文件路徑上調用「readdir」或「scandir」,或使用帶有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造成的。

我正在考慮編寫一個簡單的webapp,它將在文件文件webserver上運行,並通過API提供對目錄結構的實時查詢。

我會很感激任何想法或建議。

+0

從網站訪問文件系統通常被認爲是這種原因的不好做法。我建議你將目錄結構寫入一個數據庫(如果必須的話,或xml文件),然後將其讀出而不是擊中文件系統。捕獲創建新的目錄調用並使其更新目錄結構DB – Ewan 2015-03-13 13:58:20

+0

另一種解決方案 - 可以用一些字符串爲所有目錄加上前綴,當你用文件得到列表時,可以通過檢查它們是否包含字符串來檢查哪些目錄實際上是目錄。你可以完全避免'is_dir()'這種方式。 – VolenD 2015-03-13 17:08:52

+0

@Ewan我們曾考慮過使用單獨的數據結構來跟蹤所有的文件和文件夾,但這樣做的缺點是會導致系統中出現兩個「真相源」可以通過前端Web服務器引用和訪問的實際文件系統文件,然後是管理控制面板將使用的數據庫中的文件列表 - 這兩個文件需要保持同步,這隻會增加複雜性。 – 2015-03-16 02:54:52

回答

0

另一種解決方案 - 你可以用一些字符串前綴所有目錄,當你用文件得到列表時,你可以通過檢查它們是否包含字符串來檢查哪些是實際目錄。您可以完全避免is_dir()這種方式。

相關問題