大家都知道ASP.NET 網站應用程式程式(WebSite)可以自動檢測到你的ASP.NET應用的檔案修改,其中要使用到的就是監視磁碟上的檔案/目錄的更改,以便應用程式可以採取它認為必要檔案建立/刪除/修改事件的反應中的任何步驟的FileSystemWatcher 類。
Mono的 FileSystemWatcher實現盡了最大的努力適應各種環境(Linux/Windows/*BSD),在各種作業系統環境下執行其分配的任務,在Unix環境下支援以下後端的系統:
- FAM
- kevent (BSD*/MacOSX only)
- gamin
- inotify (Linux only)
- Managed watcher
其中,假設您運行 Linux(核心2.6.13以上), inotify是一種首選的後端機制因為它需要對使用者態應用程式的一部分,他不是使用輪詢而是使用 Linux 核心的通知機制 (在我們的例子,Mono的運行庫)。然而,它需要 Linux 核心來支援機制。
如果你的核心不支援inotify,Mono將嘗試使用FAM和gamin 這樣的使用者態的應用程式來監測檔案系統的檔案/目錄的更改,然後通知到Mono運行時,這樣效率就大打折扣了,效能就很糟糕了。如果Mono 都無法檢測到inotify,Fam以及gamin,mono將使用最後一個選項Managed watcher,此監測程式在Managed 程式碼中實現,並為監測、 輪詢更改所選檔案/目錄上的檔案系統使用一個單獨的線程。由於應用程式可能 (和在 ASP.NET 的情況下有時不會)遞迴查看目錄,它可能會非常昂貴的情況,需要檢查更改為一大組的檔案。每個啟動並執行變化檢測需要檢查檔案/目錄是否存在 (以防託管觀察程式這些都是兩個 stat (2) 調用),然後檢查更改的檔案中繼資料 (大小、 修改時間等),產生一個事件。大約每750ms發生一次,並給伺服器的 CPU 上帶來大量的負載,導致CPU飆升。
解決方案也很簡單,如果你可以的話的關閉檔案系統監測 (這意味著您的ASP.NET應用程式將不自動重新啟動修改 Web.config 時,不會重新編譯檔案,如果您修改程式碼後置.cs 或.aspx、.ascx 檔案等)。Mono支援MONO_MANAGED_WATCHER環境變數 設定為值disable,減輕您的應用程式做上面所述的檔案系統輪詢事務,既然是生產環境,就不會有什麼經常性更新關閉這個特性也不會有大的影響,還可以節約背景線程資源 。
在linux上跑ASP.NET網站,有時cpu會出現佔用率比較高的情況,過段時間它又正常了,在VPS中,這樣情況出現的機率更大,處理方法:
1、不必管它,它自然會降下來,只是等的時間要長一點,而且有可能過段時間又出現,原因就是上述說明,如果是VPS或者雲主機上出現這個問題,你一定得好好的分析下原因,是不是就是有這個特性引起的,如果是就把他關掉;
2、使用Jexus 跑ASP.NET網站,在jws.start/jws.restart兩個檔案中,插一句:export MONO_MANAGED_WATCHER=disable,禁止ASP.NET自動檢測,當然副作用是:你修改源碼後,得手工重啟這個網站。
3、使用Apache的 Mod_mono 使用命令 MonoSetEnv [server_alias] MONO_MANAGED_WATCHER=disable
可以使用下面的代碼檢測你的Linux伺服器上使用的是哪個FileSystemWatcher 實現
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
namespace FileWatchDetect
{
class Program
{
static void Main(string[] args)
{
object watcher = new FileSystemWatcher().GetType()
.GetField("watcher", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);
Console.WriteLine(watcher != null ? watcher.GetType().FullName : "unknown");
Console.Read();
}
}
}
下面的結果是在Windows Azure上的一台OpenSuse 12.0.4上的運行:
Inotify: 高效、即時的Linux檔案系統事件監控架構
使用FAM來監視linux檔案系統變化
Tip: Mono ASP.NET application burning CPU in idle state - FileSystemWatcher