WebJobs不是Azure和.NET中的新事物。 Visual Studio 2017中甚至還有一個預設的Azure WebJob模板,用於完整的.NET Framework。 但是,Visual Studio中以某種方式遺漏了.NET Core中WebJobs的類似模板。 在這篇文章中,我使用的 ...
WebJobs不是Azure和.NET中的新事物。 Visual Studio 2017中甚至還有一個預設的Azure WebJob模板,用於完整的.NET Framework。 但是,Visual Studio中以某種方式遺漏了.NET Core中WebJobs的類似模板。 在這篇文章中,我使用的是.NET Core 2.1來創建WebJobs。
在.NET Core中創建WebJob並不難,但你必須知道一些技巧,特別是如果你想使用一些.NET Core好特性,比如日誌和DI。
在這篇文章中,我們將構建一個WebJob並使用Visual Studio,Azure門戶和VSTS將其發佈到Azure。
什麼是WebJobs
WebJob是在App Service後臺運行的程式。 它與您的Web應用程式在相同的環境中運行,無需額外費用。 也許你需要做一些每小時任務或每天凌晨1點做一些清理工作。 Azure Application Insights使用WebJob報告應用程式的統計信息。
WebJobs可以按小時或每天安排,但也可以觸發。 觸發器可以是文件上傳或隊列上的新消息。
WebJobs 對比 Functions
我經常在WebJobs和Azure Functions之間比較。 在某種程度上,Functions是WebJobs的後繼者。 Functions(通常)是在Azure中運行的一小段代碼,就像WebJobs一樣,在某個事件中觸發,包括HTTP觸發器。
Functions通常是WebJobs的一個很好的替代品,但如果你已經有了一個Web應用程式,那麼使用WebJob就可以了。 特別是當您想在WebJob和Web應用程式之間共用代碼或設置,這也使部署非常容易,因為它們在相同的上下文中運行。
創建一個Storage賬戶
在我們繼續之前,先讓我們先處理一下。 WebJob需要Azure Storage賬戶。 我將快速引導您完成創建過程。
在Azure中,找到“Storage Azure( 存儲帳戶)”並添加一個。 您必須選擇一個在Azure中唯一的名稱。 除此之外,您可以保留預設值。
一旦你的 Storage Account就緒,選擇它並找到您的“Access keys(訪問密鑰)”。 我們稍後需要的兩個連接字元串之一。
創建WebJob
前面已經說過,完整的.NET Framework有一個WebJob模板。 我建議你看看。 首先創建一個ASP.NET Web應用程式,然後添加一個新的WebJob。 如果您嘗試立即創建WebJob,則會收到錯誤消息,指出項目需要先保存(儘管它確實創建了WebJob)。
這邊文章寫的是.NET Core的WebJob。 首先,創建一個ASP.NET Core Web應用程式,然後將新的.NET Core Console應用程式項目添加到您的解決方案中。
我們需要做的第一件事是從NuGet安裝Microsoft.Azure.WebJobs包。 我們還應該安裝Microsoft.Azure.WebJobs.Extensions。 這些庫的最新穩定版本依賴於完整的.NET Framework,因此我們將需要3.0.0-beta5版本(在撰寫本文時),它與.NET Core完全相容。
我們需要的其他NuGet包是Microsoft.Extensions.Options.ConfigurationExtensions(它還提供了我們還需要的Microsoft.Extensions.Options包),Microsoft.Extensions.DependencyInjection和Microsoft.Extensions.Logging.Console。 請確保全裝這些軟體包的2.1.0版本,因為.NET Core 2.1中似乎存在一個錯誤,導致您無法使用包含修補程式版本的軟體包,例如2.1.1。
添加到Program.cs文件
我們需要做的下一件事是更改我們的Program.cs文件。 如果您使用.NET Framework模板創建了WebJob,則只需複製並粘貼在那裡生成的Program.cs文件(您可能需要更改命名空間)。
using Microsoft.Azure.WebJobs; namespace NetCoreWebJob.WebJob { // To learn more about Microsoft Azure WebJobs SDK, please see https://go.microsoft.com/fwlink/?LinkID=320976 internal class Program { // Please set the following connection strings in app.config for this WebJob to run: // AzureWebJobsDashboard and AzureWebJobsStorage private static void Main() { var config = new JobHostConfiguration(); if (config.IsDevelopment) { config.UseDevelopmentSettings(); } var host = new JobHost(config); // The following code ensures that the WebJob will be running continuously host.RunAndBlock(); } } }
添加配置和依賴
您會用到.NET Core裡面好的特性,比如日誌和DI。 預設情況下,Console App不具備任何功能,但您可以自行添加。
private static void Main() { IServiceCollection services = new ServiceCollection(); ConfigureServices(services); // ... } private static IConfiguration Configuration { get; set; } private static void ConfigureServices(IServiceCollection services) { var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); Configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile($"appsettings.{environment}.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables() .Build(); services.AddSingleton(Configuration); services.AddTransient<Functions, Functions>(); services.AddLogging(builder => builder.AddConsole()); }
接下來,創建一個appsettings.json文件並將“複製到輸出目錄”屬性設置為“始終複製”。 appsettings.json文件應該有兩個連接字元串,如Program.cs模板文件中所述。 這些是我們之前創建的存儲帳戶連接字元串。
{ "Logging": { "LogLevel": { "Default": "Warning" } }, "ConnectionStrings": { "AzureWebJobsDashboard": "[your Storage Account connection string]", "AzureWebJobsStorage": "[your Storage Account connection string]" } }
接下來我們需要的是一個自定義的IJobActivator,可用於將依賴項註入到我們的類中。 它需要在Program類的JobHostConfiguration上設置。
using Microsoft.Azure.WebJobs.Host; using Microsoft.Extensions.DependencyInjection; using System; namespace NetCoreWebJob.WebJob { public class JobActivator : IJobActivator { private readonly IServiceProvider services; public JobActivator(IServiceProvider services) { this.services = services; } public T CreateInstance<T>() { return services.GetService<T>(); } } }
var config = new JobHostConfiguration(); config.JobActivator = new JobActivator(services.BuildServiceProvider());
添加Trigger(觸發器)
之後,創建一個類並將其命名為Functions(就像在WebJob模板中一樣)。 Functions類將包含WebJob的實際代碼。
當然,我們需要添加一個觸發器。 這與完整的.NET Framework不同。 畢竟,模板使用靜態方法,這使得DI無法實現。 說到DI,請註意我們還將Functions類本身添加到DI容器中。
為簡單起見,我們將使用TimerTrigger,它由所謂的CRON表達式觸發。 這隻是意味著它在某一分鐘,小時,一天等時觸發。在這個例子中,它會觸發每一分鐘。
我們還需要在JobHostConfiguration上配置計時器。
using Microsoft.Azure.WebJobs; using Microsoft.Extensions.Logging; using System; namespace NetCoreWebJob.WebJob { public class Functions { private readonly ILogger<Functions> logger; public Functions(ILogger<Functions> logger) { this.logger = logger; } public void ProcessQueueMessage([TimerTrigger("* * * * *")]TimerInfo timerInfo) { logger.LogInformation(DateTime.Now.ToString()); } } }
var config = new JobHostConfiguration(); config.JobActivator = new JobActivator(services.BuildServiceProvider()); config.UseTimers();
運行示例
如果您正確地執行了所有操作,或者如果您正在從GitHub運行我的代碼,那麼您現在應該能夠運行控制台應用程式。 如果您在例外情況下中斷或者您正在觀看“輸出”視窗,您可能會註意到很多StorageExceptions。 不要擔心它們,忽略它們。 這是WebJobs庫中的一個錯誤,不會影響您的程式。 您的觸發器可能需要一分鐘才會消失,所以要有一點耐心。
如果您轉到Azure存儲帳戶,您應該看到兩個Blob容器,“azure-jobs-host-output”和“azure-webjobs-hosts”。 這裡有很多東西,但你可以忽略它。 我發現我的WebJob觸發器由於某種原因不會消失,刪除Blob容器通常會有所幫助。 顯然,存儲在那裡的某些狀態在重新添加和刪除WebJobs時並不總是正確處理掉。
發佈到Azure
我們要做的下一件事是將WebJob部署到Azure。為了運行WebJob,需要一些可以用來運行的可執行腳本。支持許多文件類型,但對於我們Windows用戶來說,使用exe,cmd,bat或PowerShell文件。
控制台應用程式曾經是一個exe文件,但在.NET Core中,它會生成一個我們需要手動啟動的常規DLL文件。因此,創建一個文件並將其命名為“run.cmd”並確保它以UTF-8編碼沒有BOM(您可以使用Notepad ++之類的東西來檢查)。它只需要一行代碼,即“dotnet NetCoreWebJob.WebJob.dll”。這會運行您的控制台應用。確保將文件的“複製到輸出目錄”設置為“始終複製”。
最後一件事,由於某種原因,Azure WebJobs需要WebJob的所有依賴項,這意味著我們用來構建它的所有.NET Core包。您可以通過編輯csproj文件並將“<CopyLocalLockFileAssemblies> true </ CopyLocalLockFileAssemblies>”添加到第一個<PropertyGroup>(在“<TargetFramework>”下麵)來完成此操作。
在我們部署WebJob之前,我們需要部署我們的Web應用程式。右鍵單擊ASP.NET項目,然後單擊“發佈...”。只需按照嚮導操作,Visual Studio就會為您部署您的應用程式。您可以創建新的Web應用程式或選擇現有的應用程式。此步驟並非嚴格必要,因為您可以托管獨立的WebJobs,但這應該是熟悉的,它為您提供了我們可以用於WebJob的App Service。
使用Visual Studio發佈
使用Visual Studio部署WebJobs應該很容易。事實上,你可能已經知道如何做到這一點(儘管不這樣做)。右鍵單擊WebJob項目,然後單擊“發佈...”。以下嚮導看起來很像我們剛剛做的Web應用程式的發佈。您可以選擇“選擇現有”並選擇我們剛創建的Azure Web應用程式。
不幸的是,微軟以最糟糕的方式搞砸了這個功能。 Visual Studio將使用與項目相同的名稱部署WebJob,即“NetCoreWebJob.WebJob”,除了dot是WebJob名稱中的非法字元!這搞砸了我的項目非常糟糕我不得不手動編輯它以使我的解決方案再次運行。
所以這就是你做的。在嚮導開始時,您可以選擇新的或現有的App Service,單擊“立即發佈”旁邊的箭頭,然後選擇“創建配置文件”。現在,您可以先在設置中更改WebJob的名稱,然後再進行部署。確保您沒有選擇“刪除目的地的其他文件”,否則您將刪除您的網路應用程式。
現在,瀏覽到Azure門戶並查找您的Web應用程式。你會在菜單中找到“WebJobs”。你會看到你的WebJob,但它沒有做任何事情。您需要通過選擇它並單擊“運行”來手動運行它。狀態應更新為“正在運行”。您現在可以查看日誌以確定它確實有效。您可能會看到有關連接字元串的錯誤,但您可以忽略它們。如果您切換輸出,您仍然會看到一個日誌寫入控制台,讓您知道它的工作原理!如果您沒有立即看到日誌,請嘗試等待一兩分鐘,不要忘記手動刷新輸出。
Azure WebJobs圖
使用Azure Portal發佈
添加新的WebJob時,您需要填寫一些選項。 您可以組成一些名稱,將類型設置為“已觸發”,將觸發器設置為“手動”。 你的選擇是一個“連續”WebJob,它只是運行和關閉(除非你在你的應用程式中實現了無限迴圈); 以及“預定”觸發的工作,這基本上就是我們所擁有的,除非我們自己實施了計劃。
“文件上傳”需要一些解釋。 在這裡,您可以上傳包含WebJob的zip文件。 因此,請轉到Visual Studio並構建您的解決方案。 然後轉到WebJob項目的輸出文件夾,例如“MyProject \ bin \ [Debug | Release] \ netcoreapp2.1”,並將該文件夾中的所有內容放入zip文件中。 然後在新WebJob的“文件上傳”中選擇它。
添加 WebJob
Azure需要幾秒鐘才能創建您的WebJob,因此請在刷新之前保持刷新。 之後,您必須再次手動啟動它,您可以查看日誌。
使用VSTS發佈
最終,我們希望將我們的WebJob添加到VSTS中的CI / CD管道中。 不幸的是,這個功能並不是即拿即用的。 幸運的是,這也不是很困難。
當您在Azure門戶中時,找到App Service的“App Service Editor(預覽)”。 這使您可以瀏覽App Service中的所有文件。 我們註意到的一件事是您的WebJob位於“App_Data \ jobs \ triggered \ [WebJob名稱]”中。 由於您的WebJob實際上只是WebJob項目構建的輸出,因此只需將WebJob文件複製到App_Data即可。
構建
所以去VSTS並創建一個新版本。選擇存儲庫,分支,然後選擇“ASP.NET Core”作為模板。我們只需要在這裡改變兩件事。我們需要更改現有的“發佈”任務並添加新的“.NET Core”任務來發佈我們的WebJob。
將現有發佈任務的名稱更改為“發佈Web應用程式”,取消選中“發佈Web項目”覆選框,然後輸入“項目路徑”,即“** / NetCoreWebJob.csproj”。此外,取消選中“Zip Published Projects”和“Add project name to publish path”覆選框,因為它們最終會破壞我們的版本。
之後,創建一個新的.NET Core任務,將“Command”設置為“publish”,並將任務名稱更改為“Publish web job”。再次,取消“發佈Web項目”並設置“項目路徑”,即“** / NetCoreWebJob.WebJob.csproj”。再次,不要壓縮已發佈的項目或將項目名稱添加到發佈路徑。這裡的最後一步是“Arguments”欄位,可以從其他發佈步驟複製/粘貼,除了我們要添加一點:“ - configuration $(BuildConfiguration) - output $(build。 artifactstagingdirectory)\ App_Data文件\ \作業引發\ WebJobVSTS”。
VSTS WebJob構建
發佈
最後,但並非最不重要的是,發佈。 在VSTS中創建新版本,選擇“Azure App Service部署”模板並填寫空白,這是工件和環境中的Azure設置。 因為我們沒有壓縮我們的構建,所以我們只需要更改一個設置。 在“部署Azure應用程式服務”任務是“包或文件夾”設置,其預設值為“[...] / * .zip”,顯然不起作用。 而是使用瀏覽器(帶有“...”的按鈕)並選擇您的drop文件夾。
保存,點擊新版本並選擇最新版本。 如果一切順利,您應該在Azure門戶中看到新的WebJob!
結束語
喜歡這篇文章就轉載吧!不要直接copy過去哦!原文地址和源代碼:使用.NET Core 2.1的Azure WebJobs