4

如何啟用 ASP.NET Core 6.0 部署到 IIS 的陰影複製 (Shadow-copying) 功能

 2 years ago
source link: https://blog.miniasp.com/post/2021/11/13/ASPNET-Core-6-Shadow-copying-in-IIS
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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 才能啟用陰影複製功能。

陰影複製設定啟用之後,其運作原理如下:

  1. 使用者發送 HTTP 要求到 IIS 站台

  2. IIS 的 ASP.NET Core Module (ANCM) 將整個站台進行複製

    所有檔案 (包含 wwwroot 資料夾) 會複製一份到 shadowCopyDirectory 指定的目錄中,網站會複製到該目錄的子資料夾中,資料夾名稱是一個流水號,每次陰影複製會累積複製到這裡,太舊的版本會自動刪除,所以該資料夾不需要人工維護。

  3. IIS 的 ASP.NET Core Module (ANCM) 會改從陰影複製資料夾啟動網站

    所以你原本部署的站台目錄下所有檔案就不會被鎖定,之後也可以順利的部署網站。

設定完成後,當你下次更新 ASP.NET Core 網站程式,IIS 的 ASP.NET Core Module (ANCM) 會自動監視到檔案變更,並且自動將網站再次複製一份到 shadowCopyDirectory 指定的目錄中,然後 IIS 會自動切換到新的陰影複製版本來執行程式,因此使用者不會感受到任何斷線時間,是不是非常棒呢! 👍


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK