ASP.NET Core 可以部署至 IIS 網站伺服器,但一直以來都有一個毛病,那就是 ASP.NET Core 網站在運行的過程中,許多 *.dll
檔案會被鎖定,導致這些檔案無法順利更新,必須暫時關閉應用程式集區才能順利對網站進行部署。從 ASP.NET Core 6.0 開始,ASP.NET Core Module 包含了一項實驗性功能名叫 陰影複製(Shadow-copying),這個功能可以徹底解決網站運行中無法部署程式的問題。
使用 app_offline.htm 關閉網站
其實一直以來,微軟官方建議的更新手段,是在網站根目錄加上 app_offline.htm 檔案,強迫關閉應用程式集區。但是這種更新方法會導致網站在更新部署的過程中無法提供服務,以致於網站中斷服務,所以一直不是很理想的部署方法。
首先,當網站加上 app_offline.htm 檔案之後,應用程式集區會立即停止運作。注意,並不是「網站」被關閉,網站其實還在,只是整個網站無論用戶端開啟任何頁面,一律只提供 app_offline.htm
檔案的內容,且所有 HTTP 要求的 Content-Type
固定為 text/html
,以及 HTTP 回應狀態碼為 503 Service Unavailable
。
不過,即便你加上了 app_offline.htm
檔案,其實還要等 ASP.NET Core 的程式停止 (Graceful Shutdown),所以這些 *.dll
檔案並不會立即解除鎖定,而檔案解鎖的時間可能會介於 1 ~ 30 秒不等,因此更新程式的時候,還需要額外實作 retry (重新嘗試) 機制,以確保 ASP.NET Core 程式可以順利更新。
使用 ASP.NET Core Module 的陰影複製 (Shadow-copying)
當我們使用 .NET SDK 的 dotnet publish
命令發行 ASP.NET Core 網站時,預設會自動產生一個給 IIS 站台專用的 web.config
檔案,其內容如下:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\WebApplication1.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
</system.webServer>
</location>
</configuration>
要啟用 ASP.NET Core Module 的 陰影複製 (Shadow-copying) 功能,必須調整 <handlerSettings>
設定如下:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\WebApplication1.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess">
<handlerSettings>
<handlerSetting name="experimentalEnableShadowCopy" value="true" />
<handlerSetting name="shadowCopyDirectory" value="../ShadowCopyDirectory/" />
<!-- Only enable handler logging if you encounter issues-->
<!-- <handlerSetting name="debugFile" value="../ShadowCopyLogs/aspnetcore-debug.log" /> -->
<!-- <handlerSetting name="debugLevel" value="FILE,TRACE" /> -->
</handlerSettings>
</aspNetCore>
</system.webServer>
</location>
</configuration>
注意: 請務必安裝 ASP.NET Core 6.0 的 Hosting Bundle 才能啟用陰影複製功能。
當陰影複製設定啟用之後,其運作原理如下:
-
使用者發送 HTTP 要求到 IIS 站台
-
IIS 的 ASP.NET Core Module (ANCM) 將整個站台進行複製
所有檔案 (包含 wwwroot
資料夾) 會複製一份到 shadowCopyDirectory
指定的目錄中,網站會複製到該目錄的子資料夾中,資料夾名稱是一個流水號,每次陰影複製會累積複製到這裡,太舊的版本會自動刪除,所以該資料夾不需要人工維護。
-
IIS 的 ASP.NET Core Module (ANCM) 會改從陰影複製資料夾啟動網站
所以你原本部署的站台目錄下所有檔案就不會被鎖定,之後也可以順利的部署網站。
設定完成後,當你下次更新 ASP.NET Core 網站程式,IIS 的 ASP.NET Core Module (ANCM) 會自動監視到檔案變更,並且自動將網站再次複製一份到 shadowCopyDirectory
指定的目錄中,然後 IIS 會自動切換到新的陰影複製版本來執行程式,因此使用者不會感受到任何斷線時間,是不是非常棒呢! 👍
相關連結