我們在使用 Webfarm 架構建置網站時,有許多要注意的地方,我想最麻煩的地方就是如何將使用者上傳的檔案同步到每一台主機!
因為使用者每次 Request 到 Webfarm 的主機時,不一定每次都會連線到同一台 WEB 主機,所以在執行檔案上傳時,一定不能儲存到「本機」路徑,因為你上傳到其中一台,另一台就讀不到。
一般來說會有兩種作法:
-
將檔案或文件全部都儲存到資料庫中。
-
將檔案或文件儲存到一個共享的資料夾中。
這種作法是這樣的:
- 假設我們有 4 台 WEB 主機,分別命名為
WEB1
, WEB2
, WEB3
, WEB4
。
- 共用的檔案統一儲存在
WEB4
主機 (也可以在另一台 File Server )
- 其
WEB1
... WEB4
的 IIS 都設定一組虛擬目錄 Files
,並設定對應到 \\WEB4\ShareFolder
分享目錄中,並在 IIS 設定登入到 WEB4
主機的帳號、密碼。
- 然後
WEB1
... WEB4
的 IIS 就可以用 http://WEB4/Files/
讀取 \\WEB4\ShareFolder
分享目錄中的檔案了!
不過這時問題來了!
由於 ASP.NET 在運行的時候,是採用 ASPNET
(IIS5) 或 NETWORK SERVICE
(IIS6) 身份在執行的,因此並無權限將檔案讀取或寫入到網路芳鄰的 Share Folder 中。
因為透過 IIS 是可以讀的到檔案的,但是透過 ASP.NET 卻無法正確的取得檔案!使用 System.IO.File.ReadAllText(filename)
讀取檔案內容時,就會發生 Exception!甚至連 File.Exists(filename)
都無法檢查檔案是否存在!
這很有可能會讓 .NET 新手誤以為是 .NET 的 Bug !! 其實 .NET Security 何其重要,希望各位還是抽空多瞭解相關的觀念!
備註:我們常用的 Server.MapPath("~/Files/a.txt")
套用在這種「虛擬目錄」時,會將檔案路徑替換成 \\WEB4\ShareFolder\a.txt
接下來,我分享我個人的 Best Practice,這個環境是建立在沒有 AD 的情況下,如果主機群有建立 AD 環境會簡單很多:
環境說明:
- 四台 WEB 主機 ( 沒有 AD 環境 )
- 一台 File 主機
設定步驟:
-
新增一個共用的使用者到「 File 主機」與「每一台WEB主機」,每台主機的帳號、密碼都要一樣
- 帳號:ImpersonateUser
- 密碼:KesTa8ru
-
在 File 主機新增分享目錄
分享名稱為 Files
假設實際目錄路徑為 D:\Files
-
修改目錄權限 ( File 主機 )
-
修改目錄權限 ( 所有 WEB 主機 )
-
確認 IIS 的虛擬目錄設定
- 目錄名稱:
Files
- 目的位址:
\\File1\Files
- 登入帳號:
ImpersonateUser
- 登入密碼:
KesTa8ru
-
修改網站的 web.config
在 <system.web>
底下新增 <identity>
設定,讓網站用 ImpersonateUser
的身份執行!
<identity impersonate="true" userName="ImpersonateUser" password="KesTa8ru" />
只要以上六個步驟就可以完成 Webfarm 的架構設定! 但這只有解決檔案權限的問題而已,還有許多其他的開發細節以後有時間再談。