使用.NET Core 2.1的Azure WebJobs

MSDNER發表於2018-09-07

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,但它沒有做任何事情。您需要通過選擇它並單擊“執行”來手動執行它。狀態應更新為“正在執行”。您現在可以檢視日誌以確定它確實有效。您可能會看到有關連線字串的錯誤,但您可以忽略它們。如果您切換輸出,您仍然會看到一個日誌寫入控制檯,讓您知道它的工作原理!如果您沒有立即看到日誌,請嘗試等待一兩分鐘,不要忘記手動重新整理輸出。

WebJobs in Azure

Azure WebJobs圖

使用Azure Portal釋出

新增新的WebJob時,您需要填寫一些選項。 您可以組成一些名稱,將型別設定為“已觸發”,將觸發器設定為“手動”。 你的選擇是一個“連續”WebJob,它只是執行和關閉(除非你在你的應用程式中實現了無限迴圈); 以及“預定”觸發的工作,這基本上就是我們所擁有的,除非我們自己實施了計劃。

“檔案上傳”需要一些解釋。 在這裡,您可以上傳包含WebJob的zip檔案。 因此,請轉到Visual Studio並構建您的解決方案。 然後轉到WebJob專案的輸出資料夾,例如“MyProject bin [Debug | Release] netcoreapp2.1”,並將該資料夾中的所有內容放入zip檔案中。 然後在新WebJob的“檔案上傳”中選擇它。

Add 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即可。

WebJob file location

WebJob檔案位置
 

 

構建

所以去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 build

VSTS WebJob構建

釋出

最後,但並非最不重要的是,釋出。 在VSTS中建立新版本,選擇“Azure App Service部署”模板並填寫空白,這是工件和環境中的Azure設定。 因為我們沒有壓縮我們的構建,所以我們只需要更改一個設定。 在“部署Azure應用程式服務”任務是“包或資料夾”設定,其預設值為“[…] / * .zip”,顯然不起作用。 而是使用瀏覽器(帶有“…”的按鈕)並選擇您的drop資料夾。

儲存,點選新版本並選擇最新版本。 如果一切順利,您應該在Azure門戶中看到新的WebJob!

結束語

喜歡這篇文章就轉載吧!不要直接copy過去哦!原文地址和原始碼:使用.NET Core 2.1的Azure WebJobs

相關文章