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 账户 https://docs.microsoft.com/en-us/azure/storage/common/storage-quickstart-create-account?tabs=portal . 我将快速引导您完成创建过程.
在 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 即可.
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 构建
发布
最后, 但并非最不重要的是, 发布. 在 VSTS 中创建新版本, 选择 "Azure App Service 部署" 模板并填写空白, 这是工件和环境中的 Azure 设置. 因为我们没有压缩我们的构建, 所以我们只需要更改一个设置. 在 "部署 Azure 应用程序服务" 任务是 "包或文件夹" 设置, 其默认值为 "[...] /* .zip", 显然不起作用. 而是使用浏览器 (带有 "..." 的按钮) 并选择您的 drop 文件夹.
保存, 点击新版本并选择最新版本. 如果一切顺利, 您应该在 Azure 门户中看到新的 WebJob!
结束语
来源: https://www.cnblogs.com/bruceday/p/9606725.html