ASP.NET Core如何實現簡單的靜態網站滾動更新
目錄
- Intro
- FileProviiqHtrOcder
- Construct Host
- Demo
- More
- 總結
Intro
最近我們老闆想讓我實現一個靜態“滾動更新”的功能,其實就是希望網站部署的時候網站內容完整的切換,不能網站部署的過程中一部分是www.cppcns.com新的內容,另外一部分是老的內容。
這讓我想到了微軟的 Azure App Service,上家公司主要是用微軟的雲服務 Azure,站點是部署到 Azure App Service 上的,Azure App Service 有一個部署槽的概念,我們的應用一個版本可以對應一個部署槽,通過部署槽我們就基本可以無縫地從一個版本切換到另外一個版本。
FileProvider
ASP.NET Core 裡靜態檔案的託管是允許自定義一個 IFileProvider 的,預設會使用物理路徑檔案, ASP.NET Core 預設使用 wwroot 目錄下作為預設的靜態檔案來源。
對於靜態檔案而言我們簡單地使用兩個目錄來模擬兩個部署槽,當需要的時候通過修改配置來動態修改生效的部署槽,基於 IOptionMonitor 和 PhysicalFileProvider 來實現一個簡單的 DynamicFileProvider,實現程式碼如下:
public class DynamicFileProviderOptions { public string CurrentSlot { get; set; } } public class DynamicFileProvider : IFileProvider { private PhysicalFileProvider _physicalFileProvider; private const string DefaultSlotName = "Slot1"; public DynamicFileProvider(IOptionsMonitor<DynamicFilePwww.cppcns.comroviderOptions> optionsMonitor,IWebHostEnvironment webHostEnvironment) { var webRoot = webHostEnvironment.ContentRootPath; _physicalFileProvider = new PhysicalFileProvider(Path.Combine(webRoot,optionsMonitor.CurrentValue.CurrentSlot ?? DefaultSlotName)); optionsMonitor.OnChange(options => { var path = Path.Combine(webRoot,options.CurrentSlot); _physicalFileProvider = new PhysicalFileProvider(path); }); } public IDirectoryContents GetDirectoryContents(string subpath) { return _physicalFileProvider.GetDirectoryContents(subpath); } public IFileInfo GetFileInfo(string subpath) { return _physicalFileProvider.GetFileInfo(subpath); } public IChangeToken Watch(string filter) { return _physicalFileProvider.Watch(filter); } }
看起來是不是簡單,其實就是在 PhysicalFileProvider 的基礎上封裝了一下,配置發生變化的時候構建一個新的 PhysicalFihttp://www.cppcns.comleProvider
Construct Host
接著我們來看一下如何使用,使用程式碼如下:
var builder = Host.CreateDefaultBuilder(args);
builder.ConfigureWebHostDefaults(webHostBuilder =>
{
webHostBuilder.ConfigureServices((context,services) =>
{
services.Configure<DynamicFileProviderOptions>(context.Configuration);
services.AddSingleton<DynamicFileProvider>();
});
webHostBuilder.Configure(app =>
{
var dynamicFileProvider = app.ApplicationServices.GetRequiredService<DynamicFileProvider>();
app.UseStaticFiles(new StaticFileOptions()
{
Filwww.cppcns.comeProvider = dynamicFileProvider,});
});
});
var host = builder.Build();
host.Run();
這裡的示例只需要這些程式碼我們的應用就可以跑起來了,接著我們就來看一下使用效果吧
Demo
在專案根目錄執行 dotnet run 啟動專案,然後訪問 http://localhost:5000/index.html
然後我們再修改配置檔案中的配置,把配置檔案中 CurrentSlot 配置修改為 Slot2,然後再重新整理頁面,如下圖所示:
那麼是不是可以不修改配置檔案實現部署槽切換呢,也是可以的,我提供了一個做切換的一個簡單的 API
app.Map(new PathString("/redeploy"),appBuilder => appBuilder.Run(context => { if (context.RequestServices.GetRequiredService<IConfiguration>() is ConfigurationRoot configuration) { var currentSlot = configuration["CurrentSlot"]; configuration["CurrentSlot"] = "Slot2" != currentSlot ? "Slot2" : "Slot1"; configuration.Reload(); return context.Response.WriteAsync("Success"); } return Task.CompletedTask; }));
這個 API 做的事情很簡單,在 Slot1 和 Slot2 之間進行切換,如果原來是 Slot2 則切換成 Slot1 否則切換成 Slot2,修改配置之後呼叫一下 Reload 以觸發配置更新,刪除配置檔案中的 CurrentSlot 配置,重新執行示例,檢視 http://localhost:5000/index.html,還是看到的 Slot1 中的內容,然後我們呼叫一下 /redeploy 介面來動態切換一下配置,然後再次重新整理頁面就會看到 Slot2 中的內容,再呼叫一下 redeploy 之後重新整理頁面就會變回 Slot1 中的內容
More
這樣一個簡單的 DynamicFileProvider 的功能就完成了,我們就可以動態的切換靜態資源的不同版本了。
如果實際使用的話可以考慮更新一下 redeploy 介面,把新的網站內容通過上傳檔案的形式上傳到網站下,上傳結束後觸發配置的更新,而且可以保留最近幾個版本的更新,這樣部署歷史也有了,也方便進行回滾。
可以思考一下,如果我們的站點是叢集部署的,需要改造什麼?
對於叢集部署的場景,可能會有兩個問題,一個是檔案訪問的問題, 我們可以使用一個自定義的檔案提供者來訪問檔案伺服器上的檔案,如果使用容器部署的場景,那麼我們使用同一個 Volume 就可以實現統一的檔案訪問, 另一個問題是配置的管理和更新,對於叢集部署的配置,通常我們需要使用配置中心來統一管理配置,這樣就和上面的配置一樣了,配置更新時也會觸發更新。
總結
到此這篇關於ASP.NET Core如何實現簡單的靜態網站滾動更新的文章就介紹到這了,更多相關ASP.NET Core靜態網站滾動更新內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!
References
- https://docs.microsoft.com/en-us/aspnet/core/fundamentals/static-files
- https://docs.microsoft.com/zh-cn/azure/app-service/deploy-best-practices
- https://.com/WeihanLi/SamplesInPractice/tree/master/DynamicStaticFileProvider