如何以 WebJobs 的形式运行 Durable FunctionsHow to run Durable Functions as WebJobs

默认情况下,Durable Functions 使用 Azure Functions 运行时来托管业务流程。By default, Durable Functions uses the Azure Functions runtime to host orchestrations. 但是,在某些情况下,可能需要对侦听事件的代码进行更多的控制。However, there may be certain scenarios where you need more control over the code that listens for events. 本文介绍如何使用 WebJobs SDK 来实现业务流程。This article shows you how to implement your orchestration using the WebJobs SDK.

Azure FunctionsDurable Functions 扩展构建在 WebJobs SDK 基础之上。Azure Functions and the Durable Functions extension are built on the WebJobs SDK. WebJobs SDK 中的作业主机是 Azure Functions 中的运行时。The job host in the WebJobs SDK is the runtime in Azure Functions. 如果需要以 Azure Functions 中做不到的方式来控制行为,可以使用 WebJobs SDK 自行开发并运行 Durable Functions。If you need to control behavior in ways not possible in Azure Functions, you can develop and run Durable Functions by using the WebJobs SDK yourself.

在 WebJobs SDK 的版本 3.x 中,主机是 IHost 的实现,而在版本 2.x 中,你使用 JobHost 对象。In version 3.x of the WebJobs SDK, the host is an implementation of IHost, and in version 2.x you use the JobHost object.

WebJobs SDK 2.x 版中提供了有关链接 Durable Functions 的示例:下载或克隆 Durable Functions 存储库,签出 v1** 分支,然后转到 samples\webjobssdk\chaining** 文件夹。The chaining Durable Functions sample is available in a WebJobs SDK 2.x version: download or clone the Durable Functions repository, and checkout v1 branch and go to the samples\webjobssdk\chaining folder.

先决条件Prerequisites

本文假定读者熟悉 WebJobs SDK、Azure Functions C# 类库开发和 Durable Functions 的基础知识。This article assumes you're familiar with the basics of the WebJobs SDK, C# class library development for Azure Functions, and Durable Functions. 如需这些主题的简介,请参阅以下资源:If you need an introduction to these topics, see the following resources:

完成本文中的步骤:To complete the steps in this article:

  • 安装 Visual Studio 2019(包含 Azure 开发工作负荷)。Install Visual Studio 2019 with the Azure development workload.

    如果已安装 Visual Studio,但未配置该工作负荷,请选择“工具” > “获取工具和功能”以添加该工作负荷。 If you already have Visual Studio, but don't have that workload, add the workload by selecting Tools > Get Tools and Features.

    可以改用 Visual Studio Code,但某些说明仅适用于 Visual Studio。)(You can use Visual Studio Code instead, but some of the instructions are specific to Visual Studio.)

  • 安装并运行 Azure 存储模拟器 5.2 版或更高版本。Install and run Azure Storage Emulator version 5.2 or later. 替代方法是使用 Azure 存储连接字符串更新 App.config 文件。An alternative is to update the App.config file with an Azure Storage connection string.

WebJobs SDK 版本WebJobs SDK versions

本文介绍如何开发 WebJobs SDK 2.x 项目(等效于 Azure Functions 版本 1.x)。This article explains how to develop a WebJobs SDK 2.x project (equivalent to Azure Functions version 1.x). 有关版本 3.x 的信息,请参阅本文稍后的 WebJobs SDK 3.xFor information about version 3.x, see WebJobs SDK 3.x later in this article.

创建控制台应用Create a console app

若要将 Durable Functions 作为 WebJobs 运行,必须先创建控制台应用。To run Durable Functions as WebJobs, you must first create a console app. WebJobs SDK 项目只是一个装有相应 NuGet 包的控制台应用项目。A WebJobs SDK project is just a console app project with the appropriate NuGet packages installed.

在 Visual Studio 的“新建项目”对话框中,选择“Windows 经典桌面” > “控制台应用(.NET Framework)”。 In the Visual Studio New Project dialog box, select Windows Classic Desktop > Console App (.NET Framework). 在项目文件中,TargetFrameworkVersion 应为 v4.6.1In the project file, the TargetFrameworkVersion should be v4.6.1.

Visual Studio 还有一个 WebJob 项目模板,选择“云” > “Azure WebJob (.NET Framework)”即可使用此模板。 Visual Studio also has a WebJob project template, which you can use by selecting Cloud > Azure WebJob (.NET Framework). 此模板会安装许多的包,其中一些包可能并不需要。This template installs many packages, some of which you might not need.

安装 NuGet 包Install NuGet packages

需要 WebJobs SDK 的 NuGet 包、核心绑定、日志记录框架和 Durable Task 扩展。You need NuGet packages for the WebJobs SDK, core bindings, the logging framework, and the Durable Task extension. 下面是这些包的“包管理器控制台”命令,并提供了截至编写本文时的最新稳定版本号:Here are Package Manager Console commands for those packages, with the latest stable version numbers as of the date this article was written:

Install-Package Microsoft.Azure.WebJobs.Extensions -version 2.2.0
Install-Package Microsoft.Extensions.Logging -version 2.0.1
Install-Package Microsoft.Azure.WebJobs.Extensions.DurableTask -version 1.8.3

还需要日志记录提供程序。You also need logging providers. 以下命令安装 Azure Application Insights 提供程序和 ConfigurationManagerThe following commands install the Azure Application Insights provider and the ConfigurationManager. 使用 ConfigurationManager 可从应用设置中获取 Application Insights 检测密钥。The ConfigurationManager lets you get the Application Insights instrumentation key from app settings.

Install-Package Microsoft.Azure.WebJobs.Logging.ApplicationInsights -version 2.2.0
Install-Package System.Configuration.ConfigurationManager -version 4.4.1

以下命令安装控制台提供程序:The following command installs the console provider:

Install-Package Microsoft.Extensions.Logging.Console -version 2.0.1

JobHost 代码JobHost code

创建控制台应用并安装所需的 NuGet 包以后,即可使用 Durable Functions。Having created the console app and installed the NuGet packages you need, you're ready to use Durable Functions. 可以使用 JobHost 代码来这样做。You do so by using JobHost code.

若要使用 Durable Functions 扩展,请对 Main 方法中的 JobHostConfiguration 对象调用 UseDurableTaskTo use the Durable Functions extension, call UseDurableTask on the JobHostConfiguration object in your Main method:

var config = new JobHostConfiguration();
config.UseDurableTask(new DurableTaskExtension
{
    HubName = "MyTaskHub",
};

有关可在 DurableTaskExtension 对象中设置的属性列表,请参阅 host.jsonFor a list of properties that you can set in the DurableTaskExtension object, see host.json.

Main 方法也是设置日志记录提供程序的位置。The Main method is also the place to set up logging providers. 以下示例配置控制台和 Application Insights 提供程序。The following example configures the console and Application Insights providers.

static void Main(string[] args)
{
    using (var loggerFactory = new LoggerFactory())
    {
        var config = new JobHostConfiguration();

        config.DashboardConnectionString = "";

        var instrumentationKey =
            ConfigurationManager.AppSettings["APPINSIGHTS_INSTRUMENTATIONKEY"];

        config.LoggerFactory = loggerFactory
            .AddApplicationInsights(instrumentationKey, null)
            .AddConsole();

        config.UseTimers();
        config.UseDurableTask(new DurableTaskExtension
        {
            HubName = "MyTaskHub",
        });
        var host = new JobHost(config);
        host.RunAndBlock();
    }
}

函数Functions

WebJobs 上下文中的 Durable Functions 有点不同于 Azure Functions 上下文中的 Durable Functions。Durable Functions in the context of WebJobs differs somewhat from Durable Functions in the context of Azure Functions. 在编写代码时,必须了解相关差异。It's important to be aware of the differences as you write your code.

WebJobs SDK 不支持以下 Azure Functions 功能:The WebJobs SDK doesn't support the following Azure Functions features:

FunctionName 属性FunctionName attribute

在 WebJobs SDK 项目中,函数的方法名称是函数名称。In a WebJobs SDK project, the method name of a function is the function name. FunctionName 属性只能在 Azure Functions 中使用。The FunctionName attribute is used only in Azure Functions.

HTTP 触发器HTTP trigger

WebJobs SDK 没有 HTTP 触发器。The WebJobs SDK does not have an HTTP trigger. 示例项目的业务流程客户端使用计时器触发器:The sample project's orchestration client uses a timer trigger:

public static async Task CronJob(
    [TimerTrigger("0 */2 * * * *")] TimerInfo timer,
    [OrchestrationClient] DurableOrchestrationClient client,
    ILogger logger)
{
  ...
}

HTTP 管理 APIHTTP management API

由于没有 HTTP 触发器,WebJobs SDK 没有 HTTP 管理 APIBecause it has no HTTP trigger, the WebJobs SDK has no HTTP management API.

在 WebJobs SDK 项目中,可对业务流程客户端对象调用方法,而无需发送 HTTP 请求。In a WebJobs SDK project, you can call methods on the orchestration client object, instead of by sending HTTP requests. 以下方法对应于可以使用 HTTP 管理 API 执行的三个任务:The following methods correspond to the three tasks you can do with the HTTP management API:

  • GetStatusAsync
  • RaiseEventAsync
  • TerminateAsync

示例项目中的业务流程客户端函数启动业务流程协调程序函数,然后进入每隔 2 秒调用 GetStatusAsync 的循环:The orchestration client function in the sample project starts the orchestrator function, and then goes into a loop that calls GetStatusAsync every 2 seconds:

string instanceId = await client.StartNewAsync(nameof(HelloSequence), input: null);
logger.LogInformation($"Started new instance with ID = {instanceId}.");

DurableOrchestrationStatus status;
while (true)
{
    status = await client.GetStatusAsync(instanceId);
    logger.LogInformation($"Status: {status.RuntimeStatus}, Last update: {status.LastUpdatedTime}.");

    if (status.RuntimeStatus == OrchestrationRuntimeStatus.Completed ||
        status.RuntimeStatus == OrchestrationRuntimeStatus.Failed ||
        status.RuntimeStatus == OrchestrationRuntimeStatus.Terminated)
    {
        break;
    }

    await Task.Delay(TimeSpan.FromSeconds(2));
}

运行示例Run the sample

你已经将 Durable Functions 设置为以 WebJob 方式运行,并且已了解其与以独立 Azure Functions 形式运行 Durable Functions 时的区别。You've got Durable Functions set up to run as a WebJob, and you now have an understanding of how this will differ from running Durable Functions as standalone Azure Functions. 此时可以在示例中查看其运行情况。At this point, seeing it work in a sample might be helpful.

本部分概述如何运行示例项目This section provides an overview of how to run the sample project. 有关如何在本地运行 WebJobs SDK 项目并将其部署到 Azure WebJob 的详细说明,请参阅 WebJobs SDK 入门For detailed instructions that explain how to run a WebJobs SDK project locally and deploy it to an Azure WebJob, see Get started with the WebJobs SDK.

在本地运行Run locally

  1. 确保存储模拟器正在运行(参阅先决条件)。Make sure the Storage emulator is running (see Prerequisites).

  2. 若要在本地运行项目时查看 Application Insights 中的日志:If you want to see logs in Application Insights when you run the project locally:

    a.a. 创建 Application Insights 资源并为其使用“常规”应用类型。Create an Application Insights resource, and use the General app type for it.

    b.b. App.config 文件中保存检测密钥。Save the instrumentation key in the App.config file.

  3. 运行该项目。Run the project.

在 Azure 中运行Run in Azure

  1. 创建 Web 应用和存储帐户。Create a web app and a storage account.

  2. 在 Web 应用中,将存储连接字符串保存到名为 AzureWebJobsStorage 的应用设置中。In the web app, save the storage connection string in an app setting named AzureWebJobsStorage.

  3. 创建 Application Insights 资源并为其使用“常规”应用类型。Create an Application Insights resource, and use the General app type for it.

  4. 将检测密钥保存到名为 APPINSIGHTS_INSTRUMENTATIONKEY 的应用设置中。Save the instrumentation key in an app setting named APPINSIGHTS_INSTRUMENTATIONKEY.

  5. 部署为 WebJobDeploy as a WebJob.

WebJobs SDK 3.xWebJobs SDK 3.x

本文介绍如何开发 WebJobs SDK 2.x 项目。This article explains how to develop a WebJobs SDK 2.x project. 如果开发 WebJobs SDK 3.x 项目,本部分有助于了解其中的差异。If you're developing a WebJobs SDK 3.x project, this section helps you understand the differences.

引入的主要更改是使用 .NET Core 而不是 .NET Framework。The main change introduced is the use of .NET Core instead of .NET Framework. 若要创建 WebJobs SDK 3.x 项目,请遵照上述说明,但操作上有以下几处差别:To create a WebJobs SDK 3.x project, the instructions are the same, with these exceptions:

  1. 创建 .NET Core 控制台应用。Create a .NET Core console app. 在 Visual Studio 的“新建项目”对话框中,选择“.NET Core” > “控制台应用(.NET Core)” 。In the Visual Studio New Project dialog box, select .NET Core > Console App (.NET Core). 项目文件指定 TargetFrameworknetcoreapp2.xThe project file specifies that TargetFramework is netcoreapp2.x.

  2. 选择以下包的 WebJobs SDK 3.x 发行版本:Choose the release version WebJobs SDK 3.x of the following packages:

    • Microsoft.Azure.WebJobs.Extensions
    • Microsoft.Azure.WebJobs.Extensions.Storage
    • Microsoft.Azure.WebJobs.Logging.ApplicationInsights
  3. 使用 .NET Core 配置框架在 appsettings.json 文件中设置存储连接字符串和 Application Insights 检测密钥。Set the storage connection string and the Application Insights instrumentation key in an appsettings.json file, by using the .NET Core configuration framework. 下面是一个示例:Here's an example:

        {
            "AzureWebJobsStorage": "<replace with storage connection string>",
            "APPINSIGHTS_INSTRUMENTATIONKEY": "<replace with Application Insights instrumentation key>"
        }
    
  4. 更改 Main 方法代码以执行此操作。Change the Main method code to do this. 下面是一个示例:Here's an example:

    static void Main(string[] args)
    {
         var hostBuilder = new HostBuilder()
             .ConfigureWebJobs(config =>
             {
                 config.AddAzureStorageCoreServices();
                 config.AddAzureStorage();
                 config.AddTimers();
                 config.AddDurableTask(options =>
                 {
                     options.HubName = "MyTaskHub";
                     options.AzureStorageConnectionStringName = "AzureWebJobsStorage";
                 });
             })
             .ConfigureLogging((context, logging) =>
             {
                 logging.AddConsole();
                 logging.AddApplicationInsights(config =>
                 {
                     config.InstrumentationKey = context.Configuration["APPINSIGHTS_INSTRUMENTATIONKEY"];
                 });
             })
             .UseConsoleLifetime();
    
         var host = hostBuilder.Build();
    
         using (host)
         {
             host.Run();
         }
    }
    

后续步骤Next steps

若要详细了解 WebJobs SDK,请参阅如何使用 WebJobs SDKTo learn more about the WebJobs SDK, see How to use the WebJobs SDK.