如何使用 Azure WebJobs SDK 进行事件驱动的后台处理How to use the Azure WebJobs SDK for event-driven background processing

本文提供有关如何使用 Azure WebJobs SDK 的指导。This article provides guidance on how to work with the Azure WebJobs SDK. 若要立即开始使用 WebJobs,请参阅用于事件驱动式后台处理的 Azure WebJobs SDK 入门To get started with WebJobs right away, see Get started with the Azure WebJobs SDK for event-driven background processing.

WebJobs SDK 版本WebJobs SDK versions

下面是 WebJobs SDK 版本 3.x 与版本 2.x 之间的重要差别:These are the key differences between version 3.x and version 2.x of the WebJobs SDK:

  • 版本 3.x 中添加了对 .NET Core 的支持。Version 3.x adds support for .NET Core.
  • 在版本 3.x 中,需要显式安装 WebJobs SDK 所需的存储绑定扩展。In version 3.x, you need to explicitly install the Storage binding extension required by the WebJobs SDK. 在版本 2.x 中,存储绑定包含在 SDK 中。In version 2.x, the Storage bindings were included in the SDK.
  • 用于 .NET Core 的 Visual Studio 工具 (3.x) 项目不同于 .NET Framework 工具 (2.x) 项目。Visual Studio tooling for .NET Core (3.x) projects differs from tooling for .NET Framework (2.x) projects. 有关详细信息,请参阅使用 Visual Studio 开发和部署 WebJob - Azure 应用服务To learn more, see Develop and deploy WebJobs using Visual Studio - Azure App Service.

本文会尽量提供同时适用于版本 3.x 和版本 2.x 的示例。When possible, examples are provided for both version 3.x and version 2.x.

Note

Azure Functions 是基于 WebJobs SDK 构建的,本文提供了适用于某些主题的 Azure Functions 文档的链接。Azure Functions is built on the WebJobs SDK, and this article provides links to Azure Functions documentation for some topics. 注意 Functions 与 WebJobs SDK 之间的以下差异:Note these differences between Functions and the WebJobs SDK:

  • Azure Functions 版本 2.x 对应于 WebJobs SDK 版本 3.x,Azure Functions 1.x 对应于 WebJobs SDK 2.xAzure Functions version 2.x corresponds to WebJobs SDK version 3.x, and Azure Functions 1.x corresponds to WebJobs SDK 2.x. 源代码存储库使用 WebJobs SDK 编号。Source code repositories use the WebJobs SDK numbering.
  • Azure Functions C# 类库的示例代码类似于 WebJobs SDK 代码,不过,在 WebJobs SDK 项目中,无需指定 FunctionName 特性。Sample code for Azure Functions C# class libraries is like WebJobs SDK code, except you don't need a FunctionName attribute in a WebJobs SDK project.
  • 某些绑定类型,例如 HTTP (Webhook) 以及基于 HTTP 的事件网格,只在 Functions 中受支持。Some binding types are supported only in Functions, like HTTP (Webhooks) and Event Grid (which is based on HTTP).

WebJobs 主机WebJobs host

主机是函数的运行时容器。The host is a runtime container for functions. 它会侦听触发器并调用函数。It listens for triggers and calls functions. 在版本 3.x 中,主机是 IHost 的实现。In version 3.x, the host is an implementation of IHost. 在版本 2.x 中,使用的是 JobHost 对象。In version 2.x, you use the JobHost object. 在代码中创建主机实例,并编写代码来自定义其行为。You create a host instance in your code and write code to customize its behavior.

这是直接使用 WebJobs SDK 与通过 Azure Functions 间接使用它的主要差别。This is a key difference between using the WebJobs SDK directly and using it indirectly through Azure Functions. 在 Azure Functions 中,由于由服务控制主机,因此无法通过编写代码来定义主机。In Azure Functions, the service controls the host, and you can't customize the host by writing code. Azure Functions 允许通过 host.json 文件中的设置自定义主机行为。Azure Functions lets you customize host behavior through settings in the host.json file. 这些设置是字符串而不是代码,限制可执行的自定义类型。Those settings are strings, not code, and this limits the kinds of customizations you can do.

主机连接字符串Host connection strings

在本地运行时,WebJobs SDK 在 local.settings.json 文件中查找 Azure 存储和 Azure 服务总线连接字符串;在 Azure 中运行时,它会在 WebJob 的环境中查找这些字符串。The WebJobs SDK looks for Azure Storage and Azure Service Bus connection strings in the local.settings.json file when you run locally, or in the environment of the WebJob when you run in Azure. 默认情况下,需要名为 AzureWebJobsStorage 的存储连接字符串设置。By default, a storage connection string setting named AzureWebJobsStorage is required.

使用版本 2.x 的 SDK,可以对这些连接字符串使用自己的名称,或将其存储于其他位置。Version 2.x of the SDK lets you use your own names for these connection strings or store them elsewhere. 可在代码中使用 JobHostConfiguration 设置名称,如下所示:You can set names in code using the JobHostConfiguration, as shown here:

static void Main(string[] args)
{
    var _storageConn = ConfigurationManager
        .ConnectionStrings["MyStorageConnection"].ConnectionString;

    //// Dashboard logging is deprecated; use Application Insights.
    //var _dashboardConn = ConfigurationManager
    //    .ConnectionStrings["MyDashboardConnection"].ConnectionString;

    JobHostConfiguration config = new JobHostConfiguration();
    config.StorageConnectionString = _storageConn;
    //config.DashboardConnectionString = _dashboardConn;
    JobHost host = new JobHost(config);
    host.RunAndBlock();
}

由于版本 3.x 使用默认的 .NET Core 配置 API,因此没有 API 可用于更改连接字符串名称。Because version 3.x uses the default .NET Core configuration APIs, there is no API to change connection string names.

主机开发设置Host development settings

可在开发模式下运行主机,提高本地开发效率。You can run the host in development mode to make local development more efficient. 下面介绍部分设置,这些设置在开发模式下运行时会发生更改:Here are some of the settings that are changed when you run in development mode:

属性Property 开发设置Development setting
Tracing.ConsoleLevel TraceLevel.Verbose:最大化日志输出。TraceLevel.Verbose to maximize log output.
Queues.MaxPollingInterval 使用较小的值可确保立即触发队列方法。A low value to ensure queue methods are triggered immediately.
Singleton.ListenerLockPeriod 使用 15 秒值有助于实现快速迭代开发。15 seconds to aid in rapid iterative development.

启用开发模式的过程取决于 SDK 版本。The process for enabling development mode depends on the SDK version.

版本 3.xVersion 3.x

版本 3.x 使用标准 ASP.NET Core API。Version 3.x uses the standard ASP.NET Core APIs. HostBuilder 实例调用 UseEnvironment 方法。Call the UseEnvironment method on the HostBuilder instance. 传递名为 development 的字符串,如以下示例中所示:Pass a string named development, as in this example:

static void Main()
{
    var builder = new HostBuilder();
    builder.UseEnvironment("development");
    builder.ConfigureWebJobs(b =>
            {
                b.AddAzureStorageCoreServices();
            });
    var host = builder.Build();
    using (host)
    {
        host.Run();
    }
}

版本 2.xVersion 2.x

JobHostConfiguration 类具有 UseDevelopmentSettings 方法,该方法支持开发模式。The JobHostConfiguration class has a UseDevelopmentSettings method that enables development mode. 以下示例演示如何使用开发设置。The following example shows how to use development settings. 若要使 config.IsDevelopment 在本地运行时返回 true,请设置名为 AzureWebJobsEnv、值为 Development 的本地环境变量。To make config.IsDevelopment return true when it runs locally, set a local environment variable named AzureWebJobsEnv with the value Development.

static void Main()
{
    config = new JobHostConfiguration();

    if (config.IsDevelopment)
    {
        config.UseDevelopmentSettings();
    }

    var host = new JobHost(config);
    host.RunAndBlock();
}

管理并发连接数(版本 2.xManaging concurrent connections (version 2.x)

在版本 3.x 中,连接限制默认为无限次连接。In version 3.x, the connection limit defaults to infinite connections. 如果出于某种原因需要更改此限制,则可以使用 WinHttpHander 类的 MaxConnectionsPerServer 属性。If for some reason you need to change this limit, you can use the MaxConnectionsPerServer property of the WinHttpHander class.

在版本 2.x 中,使用 ServicePointManager.DefaultConnectionLimit API 控制主机的并发连接数。In version 2.x, you control the number of concurrent connections to a host by using the ServicePointManager.DefaultConnectionLimit API. 在 2.x 中,应在启动 WebJobs 主机之前,在默认值 2 的基础上增大此值。In 2.x, you should increase this value from the default of 2 before starting your WebJobs host.

使用 HttpClient 从某个函数发出的所有传出 HTTP 请求都会流经 ServicePointManagerAll outgoing HTTP requests that you make from a function by using HttpClient flow through ServicePointManager. 达到 DefaultConnectionLimit 中设置的值后,ServicePointManager 会开始将请求排队,然后再发送请求。After you reach the value set in DefaultConnectionLimit, ServicePointManager starts queueing requests before sending them. 假设 DefaultConnectionLimit 设置为 2,并且代码发出了 1,000 个 HTTP 请求。Suppose your DefaultConnectionLimit is set to 2 and your code makes 1,000 HTTP requests. 最初,只允许 2 个请求传入 OS。Initially, only two requests are allowed through to the OS. 其他 998 个请求将会排队,直到有可用的空间。The other 998 are queued until there’s room for them. 这意味着 HttpClient 可能会超时,因为它似乎已发出请求,但是,OS 从未将此请求发送到目标服务器。That means your HttpClient might time out because it appears to have made the request, but the request was never sent by the OS to the destination server. 因此,可能会出现看似不合理的行为:本地 HttpClient 花费了 10 秒来完成请求,但服务在 200 毫秒内就返回了每个请求。So you might see behavior that doesn't seem to make sense: your local HttpClient is taking 10 seconds to complete a request, but your service is returning every request in 200 ms.

ASP.NET 应用程序的默认值是 Int32.MaxValue,这可能非常适合在“基本”或更高级别应用服务计划中运行的 WebJob。The default value for ASP.NET applications is Int32.MaxValue, and that's likely to work well for WebJobs running in a Basic or higher App Service Plan. WebJob 通常需要 Always On 设置,该设置仅受“基本”和更高级别应用服务计划的支持。WebJobs typically need the Always On setting, and that's supported only by Basic and higher App Service Plans.

如果 WebJob 在“免费”或“共享”应用服务计划中运行,则应用程序会受到应用服务沙盒的限制:当前的连接限制为 300 个If your WebJob is running in a Free or Shared App Service Plan, your application is restricted by the App Service sandbox, which currently has a connection limit of 300. 如果在 ServicePointManager 中指定无限制的连接数,则很有可能会达到沙盒连接阈值,并且站点将会关闭。With an unbound connection limit in ServicePointManager, it's more likely that the sandbox connection threshold will be reached and the site will shut down. 在这种情况下,将 DefaultConnectionLimit 设置为更小的值(例如 50 或 100)可以防止此问题发生,同时仍可保持足够的吞吐量。In that case, setting DefaultConnectionLimit to something lower, like 50 or 100, can prevent this from happening and still allow for sufficient throughput.

必须在发出任何 HTTP 请求之前配置该设置。The setting must be configured before any HTTP requests are made. 出于此原因,WebJobs 主机不应自动尝试调整该设置。For this reason, the WebJobs host shouldn't adjust the setting automatically. 在主机启动之前可能已发生 HTTP 请求,因而可能导致意外的行为。There could be HTTP requests that occur before the host starts, which could lead to unexpected behavior. 最佳的做法是先在 Main 方法中设置值,紧接着初始化 JobHost,如下所示:The best approach is to set the value immediately in your Main method before initializing JobHost, as shown here:

static void Main(string[] args)
{
    // Set this immediately so that it's used by all requests.
    ServicePointManager.DefaultConnectionLimit = Int32.MaxValue;

    var host = new JobHost();
    host.RunAndBlock();
}

触发器Triggers

函数必须是公共方法,并且必须包含一个触发器特性或 NoAutomaticTrigger 特性。Functions must be public methods and must have one trigger attribute or the NoAutomaticTrigger attribute.

自动触发器Automatic triggers

自动触发器调用函数来响应事件。Automatic triggers call a function in response to an event. 以下示例函数由添加到 Azure 队列存储的消息触发。Consider this example of a function that's triggered by a message added to Azure Queue storage. 该函数的响应方式是从 Azure Blob 存储中读取 Blob:It responds by reading a blob from Azure Blob storage:

public static void Run(
    [QueueTrigger("myqueue-items")] string myQueueItem,
    [Blob("samples-workitems/{myQueueItem}", FileAccess.Read)] Stream myBlob,
    ILogger log)
{
    log.LogInformation($"BlobInput processed blob\n Name:{myQueueItem} \n Size: {myBlob.Length} bytes");
}

QueueTrigger 特性告知运行时,每当某个队列消息显示在 myqueue-items 队列中,就要调用该函数。The QueueTrigger attribute tells the runtime to call the function whenever a queue message appears in the myqueue-items queue. Blob 特性告知运行时要使用队列消息读取 sample-workitems 容器中的 Blob。The Blob attribute tells the runtime to use the queue message to read a blob in the sample-workitems container. myQueueItem 参数中传递给函数的队列消息的内容是 Blob 的名称。The content of the queue message, passed in to the function in the myQueueItem parameter, is the name of the blob.

Note

Web 应用可在进入非活动状态 20 分钟后超时。A web app can time out after 20 minutes of inactivity. 只有向实际 Web 应用发出的请求才会重置计时器。Only requests to the actual web app reset the timer. 在 Azure 门户中查看应用的配置或向高级工具站点 (https://<app_name>.scm.chinacloudsites.cn) 发出请求不会重置计时器。Viewing the app's configuration in the Azure portal or making requests to the advanced tools site (https://<app_name>.scm.chinacloudsites.cn) don't reset the timer. 如果应用运行连续或计划的 Web 作业,可启用 Always On 来确保 Web 作业可靠运行。If your app runs continuous or scheduled WebJobs, enable Always On to ensure that the WebJobs run reliably. 此功能仅在基本、标准和高级定价层中提供。This feature is available only in the Basic, Standard, and Premium pricing tiers.

手动触发器Manual triggers

若要手动触发函数,请使用 NoAutomaticTrigger 特性,如下所示:To trigger a function manually, use the NoAutomaticTrigger attribute, as shown here:

[NoAutomaticTrigger]
public static void CreateQueueMessage(
ILogger logger,
string value,
[Queue("outputqueue")] out string message)
{
    message = value;
    logger.LogInformation("Creating queue message: ", message);
}

手动触发函数的过程取决于 SDK 版本。The process for manually triggering the function depends on the SDK version.

版本 3.xVersion 3.x

static async Task Main(string[] args)
{
    var builder = new HostBuilder();
    builder.ConfigureWebJobs(b =>
    {
        b.AddAzureStorageCoreServices();
        b.AddAzureStorage();
    });
    var host = builder.Build();
    using (host)
    {
        var jobHost = host.Services.GetService(typeof(IJobHost)) as JobHost;
        var inputs = new Dictionary<string, object>
        {
            { "value", "Hello world!" }
        };

        await host.StartAsync();
        await jobHost.CallAsync("CreateQueueMessage", inputs);
        await host.StopAsync();
    }
}

版本 2.xVersion 2.x

static void Main(string[] args)
{
    JobHost host = new JobHost();
    host.Call(typeof(Program).GetMethod("CreateQueueMessage"), new { value = "Hello world!" });
}

输入和输出绑定Input and output bindings

通过输入绑定能够以声明方式将 Azure 或第三方服务中的数据提供给代码使用。Input bindings provide a declarative way to make data from Azure or third-party services available to your code. 输出绑定提供更新数据的方式。Output bindings provide a way to update data. 入门文章中演示了输入和输出绑定的示例。The Get started article shows an example of each.

通过将属性应用于方法返回值,可以对输出绑定使用方法返回值。You can use a method return value for an output binding by applying the attribute to the method return value. 请参阅使用 Azure 函数返回值中的示例。See the example in Using the Azure Function return value.

绑定类型Binding types

安装和管理绑定类型的过程取决于使用的是 SDK 版本 3.x 还是版本 2.xThe process for installing and managing binding types depends on whether you're using version 3.x or version 2.x of the SDK. 可以在特定绑定类型的 Azure Functions 参考文章的“包”部分找到要为该绑定类型安装的包。You can find the package to install for a particular binding type in the "Packages" section of that binding type's Azure Functions reference article. 异常是 Files 触发器和绑定(适用于本地文件系统),不受 Azure Functions 的支持。An exception is the Files trigger and binding (for the local file system), which isn't supported by Azure Functions.

版本 3.xVersion 3.x

在版本 3.x 中,存储绑定包含在 Microsoft.Azure.WebJobs.Extensions.Storage 包中。In version 3.x, the storage bindings are included in the Microsoft.Azure.WebJobs.Extensions.Storage package. ConfigureWebJobs 方法中调用 AddAzureStorage 扩展方法,如下所示:Call the AddAzureStorage extension method in the ConfigureWebJobs method, as shown here:

static void Main()
{
    var builder = new HostBuilder();
    builder.ConfigureWebJobs(b =>
            {
                b.AddAzureStorageCoreServices();
                b.AddAzureStorage();
            });
    var host = builder.Build();
    using (host)
    {
        host.Run();
    }
}

若要使用其他触发器和绑定类型,请安装包含这些类型的 NuGet 包,并调用在扩展中实现的 Add<binding> 扩展方法。To use other trigger and binding types, install the NuGet package that contains them and call the Add<binding> extension method implemented in the extension. 例如,若要使用 Azure Cosmos DB 绑定,请安装 Microsoft.Azure.WebJobs.Extensions.CosmosDB 并调用 AddCosmosDB,如下所示:For example, if you want to use an Azure Cosmos DB binding, install Microsoft.Azure.WebJobs.Extensions.CosmosDB and call AddCosmosDB, like this:

static void Main()
{
    var builder = new HostBuilder();
    builder.ConfigureWebJobs(b =>
            {
                b.AddAzureStorageCoreServices();
                b.AddCosmosDB();
            });
    var host = builder.Build();
    using (host)
    {
        host.Run();
    }
}

若要使用属于核心服务的 Timer 触发器或 Files 绑定,请分别调用 AddTimersAddFiles 扩展方法。To use the Timer trigger or the Files binding, which are part of core services, call the AddTimers or AddFiles extension methods, respectively.

版本 2.xVersion 2.x

以下触发器和绑定类型包含在版本 2.xMicrosoft.Azure.WebJobs 包中:These trigger and binding types are included in version 2.x of the Microsoft.Azure.WebJobs package:

  • Blob 存储Blob storage
  • 队列存储Queue storage
  • 表存储Table storage

若要使用其他触发器和绑定类型,请安装包含这些类型的 NuGet 包,并对 JobHostConfiguration 对象调用 Use<binding> 方法。To use other trigger and binding types, install the NuGet package that contains them and call a Use<binding> method on the JobHostConfiguration object. 例如,若要使用 Timer 触发器,请安装 Microsoft.Azure.WebJobs.Extensions 并在 Main 方法中调用 UseTimers,如下所示:For example, if you want to use a Timer trigger, install Microsoft.Azure.WebJobs.Extensions and call UseTimers in the Main method, as shown here:

static void Main()
{
    config = new JobHostConfiguration();
    config.UseTimers();
    var host = new JobHost(config);
    host.RunAndBlock();
}

要使用 Files 绑定,请安装 Microsoft.Azure.WebJobs.Extensions 并调用 UseFilesTo use the Files binding, install Microsoft.Azure.WebJobs.Extensions and call UseFiles.

ExecutionContextExecutionContext

使用 WebJobs,可绑定到 ExecutionContextWebJobs lets you bind to an ExecutionContext. 使用此绑定,可以访问在函数签名中作为参数的 ExecutionContextWith this binding, you can access the ExecutionContext as a parameter in your function signature. 例如,以下代码使用上下文对象访问调用 ID,使用该 ID 可以关联给定函数调用生成的所有日志。For example, the following code uses the context object to access the invocation ID, which you can use to correlate all logs produced by a given function invocation.

public class Functions
{
    public static void ProcessQueueMessage([QueueTrigger("queue")] string message,
        ExecutionContext executionContext,
        ILogger logger)
    {
        logger.LogInformation($"{message}\n{executionContext.InvocationId}");
    }
}

绑定到 ExecutionContext 的过程取决于所用的 SDK 版本。The process for binding to the ExecutionContext depends on your SDK version.

版本 3.xVersion 3.x

ConfigureWebJobs 方法中调用 AddExecutionContextBinding 扩展方法,如下所示:Call the AddExecutionContextBinding extension method in the ConfigureWebJobs method, as shown here:

static void Main()
{
    var builder = new HostBuilder();
    builder.ConfigureWebJobs(b =>
            {
                b.AddAzureStorageCoreServices();
                b.AddExecutionContextBinding();
            });
    var host = builder.Build();
    using (host)
    {
        host.Run();
    }
}

版本 2.xVersion 2.x

前面所述的 Microsoft.Azure.WebJobs.Extensions 包还提供了一个可以通过调用 UseCore 方法注册的特殊绑定类型。The Microsoft.Azure.WebJobs.Extensions package mentioned earlier also provides a special binding type that you can register by calling the UseCore method. 使用此绑定可以在函数签名中定义 ExecutionContext 参数,函数签名的启用方式如下:This binding lets you define an ExecutionContext parameter in your function signature, which is enabled like this:

class Program
{
    static void Main()
    {
        config = new JobHostConfiguration();
        config.UseCore();
        var host = new JobHost(config);
        host.RunAndBlock();
    }
}

绑定配置Binding configuration

可以配置某些触发器和绑定的行为。You can configure the behavior of some triggers and bindings. 配置过程取决于 SDK 版本。The process for configuring them depends on the SDK version.

  • 版本 3.xConfigureWebJobs 中调用 Add<Binding> 方法时设置配置。Version 3.x: Set configuration when the Add<Binding> method is called in ConfigureWebJobs.
  • 版本 2.x 通过在传入 JobHost 的配置对象中设置属性来设置配置。Version 2.x: Set configuration by setting properties in a configuration object that you pass in to JobHost.

这些特定于绑定的设置相当于 Azure Functions 的 host.json 项目文件中的设置。These binding-specific settings are equivalent to settings in the host.json project file in Azure Functions.

可配置以下绑定:You can configure the following bindings:

Azure CosmosDB 触发器配置(版本 3.xAzure CosmosDB trigger configuration (version 3.x)

此示例演示如何配置 Azure Cosmos DB 触发器:This example shows how to configure the Azure Cosmos DB trigger:

static void Main()
{
    var builder = new HostBuilder();
    builder.ConfigureWebJobs(b =>
    {
        b.AddAzureStorageCoreServices();
        b.AddCosmosDB(a =>
        {
            a.ConnectionMode = ConnectionMode.Gateway;
            a.Protocol = Protocol.Https;
            a.LeaseOptions.LeasePrefix = "prefix1";

        });
    });
    var host = builder.Build();
    using (host)
    {

        host.Run();
    }
}

有关更多详细信息,请参阅 Azure CosmosDB 绑定一文。For more details, see the Azure CosmosDB binding article.

事件中心触发器配置(版本 3.xEvent Hubs trigger configuration (version 3.x)

此示例演示如何配置事件中心触发器:This example shows how to configure the Event Hubs trigger:

static void Main()
{
    var builder = new HostBuilder();
    builder.ConfigureWebJobs(b =>
    {
        b.AddAzureStorageCoreServices();
        b.AddEventHubs(a =>
        {
            a.BatchCheckpointFrequency = 5;
            a.EventProcessorOptions.MaxBatchSize = 256;
            a.EventProcessorOptions.PrefetchCount = 512;
        });
    });
    var host = builder.Build();
    using (host)
    {

        host.Run();
    }
}

有关更多详细信息,请参阅事件中心绑定一文。For more details, see the Event Hubs binding article.

队列存储触发器配置Queue storage trigger configuration

这些示例演示如何配置队列存储触发器:These examples show how to configure the Queue storage trigger:

版本 3.xVersion 3.x

static void Main()
{
    var builder = new HostBuilder();
    builder.ConfigureWebJobs(b =>
    {
        b.AddAzureStorageCoreServices();
        b.AddAzureStorage(a => {
            a.BatchSize = 8;
            a.NewBatchThreshold = 4;
            a.MaxDequeueCount = 4;
            a.MaxPollingInterval = TimeSpan.FromSeconds(15);
        });
    });
    var host = builder.Build();
    using (host)
    {

        host.Run();
    }
}

有关更多详细信息,请参阅队列存储绑定一文。For more details, see the Queue storage binding article.

版本 2.xVersion 2.x

static void Main(string[] args)
{
    JobHostConfiguration config = new JobHostConfiguration();
    config.Queues.BatchSize = 8;
    config.Queues.NewBatchThreshold = 4;
    config.Queues.MaxDequeueCount = 4;
    config.Queues.MaxPollingInterval = TimeSpan.FromSeconds(15);
    JobHost host = new JobHost(config);
    host.RunAndBlock();
}

有关更多详细信息,请参阅 host.json v1.x 参考For more details, see the host.json v1.x reference.

SendGrid 绑定配置(版本 3.xSendGrid binding configuration (version 3.x)

此示例演示如何配置 SendGrid 输出绑定:This example shows how to configure the SendGrid output binding:

static void Main()
{
    var builder = new HostBuilder();
    builder.ConfigureWebJobs(b =>
    {
        b.AddAzureStorageCoreServices();
        b.AddSendGrid(a =>
        {
            a.FromAddress.Email = "samples@functions.com";
            a.FromAddress.Name = "Azure Functions";
        });
    });
    var host = builder.Build();
    using (host)
    {

        host.Run();
    }
}

有关更多详细信息,请参阅 SendGrid 绑定一文。For more details, see the SendGrid binding article.

服务总线触发器配置(版本 3.xService Bus trigger configuration (version 3.x)

此示例演示如何配置服务总线触发器:This example shows how to configure the Service Bus trigger:

static void Main()
{
    var builder = new HostBuilder();
    builder.ConfigureWebJobs(b =>
    {
        b.AddAzureStorageCoreServices();
        b.AddServiceBus(sbOptions =>
        {
            sbOptions.MessageHandlerOptions.AutoComplete = true;
            sbOptions.MessageHandlerOptions.MaxConcurrentCalls = 16;
        });
    });
    var host = builder.Build();
    using (host)
    {

        host.Run();
    }
}

有关更多详细信息,请参阅服务总线绑定一文。For more details, see the Service Bus binding article.

其他绑定的配置Configuration for other bindings

某些触发器和绑定类型定义其自身的自定义配置类型。Some trigger and binding types define their own custom configuration types. 例如,File 触发器允许指定要监视的根路径,如以下示例中所示:For example, the File trigger lets you specify the root path to monitor, as in these examples:

版本 3.xVersion 3.x

static void Main()
{
    var builder = new HostBuilder();
    builder.ConfigureWebJobs(b =>
    {
        b.AddAzureStorageCoreServices();
        b.AddFiles(a => a.RootPath = @"c:\data\import");
    });
    var host = builder.Build();
    using (host)
    {

        host.Run();
    }
}

版本 2.xVersion 2.x

static void Main()
{
    config = new JobHostConfiguration();
    var filesConfig = new FilesConfiguration
    {
        RootPath = @"c:\data\import"
    };
    config.UseFiles(filesConfig);
    var host = new JobHost(config);
    host.RunAndBlock();
}

绑定表达式Binding expressions

在特性构造函数参数中,可以使用解析为来自各种源的值的表达式。In attribute constructor parameters, you can use expressions that resolve to values from various sources. 例如,在以下代码中,BlobTrigger 特性的路径创建名为 filename 表达式。For example, in the following code, the path for the BlobTrigger attribute creates an expression named filename. 用于输出绑定时,filename 解析为触发 Blob 的名称。When used for the output binding, filename resolves to the name of the triggering blob.

public static void CreateThumbnail(
    [BlobTrigger("sample-images/{filename}")] Stream image,
    [Blob("sample-images-sm/{filename}", FileAccess.Write)] Stream imageSmall,
    string filename,
    ILogger logger)
{
    logger.Info($"Blob trigger processing: {filename}");
    // ...
}

有关绑定表达式的详细信息,请参阅 Azure Functions 文档中的绑定表达式和模式For more information about binding expressions, see Binding expressions and patterns in the Azure Functions documentation.

自定义绑定表达式Custom binding expressions

有时,你想要在代码中指定队列名称、Blob 名称、容器或表名称,而不是进行硬编码。Sometimes you want to specify a queue name, a blob name or container, or a table name in code rather than hard-coding it. 例如,可能要在配置文件或环境变量中指定 QueueTrigger 特性的队列名称。For example, you might want to specify the queue name for the QueueTrigger attribute in a configuration file or environment variable.

为此,可以向 JobHostConfiguration 对象传入 NameResolver 对象。You can do that by passing a NameResolver object in to the JobHostConfiguration object. 在触发器或绑定特性构造函数参数中包含占位符,NameResolver 代码将提供用于取代这些占位符的实际值。You include placeholders in trigger or binding attribute constructor parameters, and your NameResolver code provides the actual values to be used in place of those placeholders. 占位符的标识方式是以百分号 (%) 将其括住,如下所示:You identify placeholders by surrounding them with percent (%) signs, as shown here:

public static void WriteLog([QueueTrigger("%logqueue%")] string logMessage)
{
    Console.WriteLine(logMessage);
}

此代码允许在测试环境中使用名为 logqueuetest 的队列,并在生产环境中使用名为 logqueueprod 的队列。This code lets you use a queue named logqueuetest in the test environment and one named logqueueprod in production. appSettings 集合中指定条目名称,而不是硬编码的队列名称。Instead of a hard-coded queue name, you specify the name of an entry in the appSettings collection.

如果未提供自定义值,则默认值 NameResolver 将会生效。There's a default NameResolver that takes effect if you don't provide a custom one. 默认设置从应用设置或环境变量中获取值。The default gets values from app settings or environment variables.

NameResolver 类从 appSettings 获取队列名称,如下所示:Your NameResolver class gets the queue name from appSettings, as shown here:

public class CustomNameResolver : INameResolver
{
    public string Resolve(string name)
    {
        return ConfigurationManager.AppSettings[name].ToString();
    }
}

版本 3.xVersion 3.x

使用依赖关系注入配置解析程序。You configure the resolver by using dependency injection. 这些示例需要下列 using 语句:These samples require the following using statement:

using Microsoft.Extensions.DependencyInjection;

可以通过调用 HostBuilder 上的 ConfigureServices 扩展方法来添加解析程序,如下例所示:You add the resolver by calling the ConfigureServices extension method on HostBuilder, as in this example:

static async Task Main(string[] args)
{
    var builder = new HostBuilder();
    var resolver = new CustomNameResolver();
    builder.ConfigureWebJobs(b =>
    {
        b.AddAzureStorageCoreServices();
    });
    builder.ConfigureServices(s => s.AddSingleton<INameResolver>(resolver));
    var host = builder.Build();
    using (host)
    {
        await host.RunAsync();
    }
}

版本 2.xVersion 2.x

NameResolver 类传入 JobHost 对象,如下所示:Pass your NameResolver class in to the JobHost object, as shown here:

 static void Main(string[] args)
{
    JobHostConfiguration config = new JobHostConfiguration();
    config.NameResolver = new CustomNameResolver();
    JobHost host = new JobHost(config);
    host.RunAndBlock();
}

Azure Functions 实现 INameResolver 以从应用设置中获取值,如以下示例中所示。Azure Functions implements INameResolver to get values from app settings, as shown in the example. 直接使用 WebJobs SDK 时,可以编写一个自定义实现,用于从偏好的任何源获取占位符替代值。When you use the WebJobs SDK directly, you can write a custom implementation that gets placeholder replacement values from whatever source you prefer.

在运行时绑定Binding at runtime

如果需要在使用 QueueBlobTable 等绑定特性之前在函数中执行某项操作,可以使用 IBinder 接口。If you need to do some work in your function before you use a binding attribute like Queue, Blob, or Table, you can use the IBinder interface.

下面的示例采用一个输入队列消息,并在输出队列中创建具有相同内容的新消息。The following example takes an input queue message and creates a new message with the same content in an output queue. 输出队列名称由函数正文中的代码设置。The output queue name is set by code in the body of the function.

public static void CreateQueueMessage(
    [QueueTrigger("inputqueue")] string queueMessage,
    IBinder binder)
{
    string outputQueueName = "outputqueue" + DateTime.Now.Month.ToString();
    QueueAttribute queueAttribute = new QueueAttribute(outputQueueName);
    CloudQueue outputQueue = binder.Bind<CloudQueue>(queueAttribute);
    outputQueue.AddMessageAsync(new CloudQueueMessage(queueMessage));
}

有关详细信息,请参阅 Azure Functions 文档中的运行时绑定For more information, see Binding at runtime in the Azure Functions documentation.

绑定参考信息Binding reference information

Azure Functions 文档中提供了有关每个绑定类型的参考信息。The Azure Functions documentation provides reference information about each binding type. 每篇绑定参考文章中介绍了以下信息。You'll find the following information in each binding reference article. (此示例基于存储队列。)(This example is based on Storage queue.)

  • Packages. 需要安装哪个包才能在 WebJobs SDK 项目中支持绑定。The package you need to install to include support for the binding in a WebJobs SDK project.
  • 示例Examples. 代码示例。Code samples. C# 类库示例适用于 WebJobs SDK。The C# class library example applies to the WebJobs SDK. 只需省略 FunctionName 特性。Just omit the FunctionName attribute.
  • 特性Attributes. 用于绑定类型的特性。The attributes to use for the binding type.
  • 配置Configuration. 特性属性和构造函数参数的解释。Explanations of the attribute properties and constructor parameters.
  • 使用情况Usage. 可绑定到哪些类型,以及有关绑定工作原理的信息。The types you can bind to and information about how the binding works. 例如:轮询算法、有害队列处理。For example: polling algorithm, poison queue processing.

有关绑定参考文章的列表,请参阅 Azure Functions 触发器和绑定一文中的“支持的绑定”。For a list of binding reference articles, see "Supported bindings" in the Triggers and bindings article for Azure Functions. 在该列表中,HTTP、Webhook 和事件网格绑定仅受 Azure Functions 的支持,而不受 WebJobs SDK 的支持。In that list, the HTTP, Webhooks, and Event Grid bindings are supported only by Azure Functions, not by the WebJobs SDK.

Disable 特性Disable attribute

Disable 特性用于控制是否可以触发某个函数。The Disable attribute lets you control whether a function can be triggered.

在以下示例中,如果应用设置 Disable_TestJob 使用值 1True(不区分大小写),则函数不会运行。In the following example, if the app setting Disable_TestJob has a value of 1 or True (case insensitive), the function won't run. 在这种情况下,运行时将创建日志消息“函数 'Functions.TestJob' 已禁用”。 In that case, the runtime creates a log message Function 'Functions.TestJob' is disabled.

[Disable("Disable_TestJob")]
public static void TestJob([QueueTrigger("testqueue2")] string message)
{
    Console.WriteLine("Function with Disable attribute executed!");
}

在 Azure 门户中更改应用设置值时,WebJob 会重启并选取新的设置。When you change app setting values in the Azure portal, the WebJob restarts to pick up the new setting.

可以在参数、方法或类级别声明该特性。The attribute can be declared at the parameter, method, or class level. 设置名称还可以包含绑定表达式。The setting name can also contain binding expressions.

Timeout 特性Timeout attribute

如果某个函数在指定的时间段内未完成,则 Timeout 特性会导致该函数被取消。The Timeout attribute causes a function to be canceled if it doesn't finish within a specified amount of time. 以下示例中的函数不带 Timeout 特性,将会运行一天。In the following example, the function would run for one day without the Timeout attribute. 如果指定了 Timeout,该函数将在 15 秒后被取消。Timeout causes the function to be canceled after 15 seconds.

[Timeout("00:00:15")]
public static async Task TimeoutJob(
    [QueueTrigger("testqueue2")] string message,
    CancellationToken token,
    TextWriter log)
{
    await log.WriteLineAsync("Job starting");
    await Task.Delay(TimeSpan.FromDays(1), token);
    await log.WriteLineAsync("Job completed");
}

可以在类或方法级别应用 Timeout 特征,并可以使用 JobHostConfiguration.FunctionTimeout 指定全局超时。You can apply the Timeout attribute at the class or method level, and you can specify a global timeout by using JobHostConfiguration.FunctionTimeout. 类级别或方法级别的超时替代全局超时。Class-level or method-level timeouts override global timeouts.

Singleton 特性Singleton attribute

Singleton 特性可确保即使有多个主机 Web 应用的实例,也只有一个函数实例运行。The Singleton attribute ensures that only one instance of a function runs, even when there are multiple instances of the host web app. 使用分布式锁定可实现此目的。It does this by using distributed locking.

在此示例中,在任意给定时间只会运行 ProcessImage 函数的单个实例:In this example, only a single instance of the ProcessImage function runs at any given time:

[Singleton]
public static async Task ProcessImage([BlobTrigger("images")] Stream image)
{
     // Process the image.
}

SingletonMode.ListenerSingletonMode.Listener

某些触发器为并发管理提供内置支持:Some triggers have built-in support for concurrency management:

  • QueueTriggerQueueTrigger. JobHostConfiguration.Queues.BatchSize 设置为 1Set JobHostConfiguration.Queues.BatchSize to 1.
  • ServiceBusTriggerServiceBusTrigger. ServiceBusConfiguration.MessageOptions.MaxConcurrentCalls 设置为 1Set ServiceBusConfiguration.MessageOptions.MaxConcurrentCalls to 1.
  • FileTriggerFileTrigger. FileProcessor.MaxDegreeOfParallelism 设置为 1Set FileProcessor.MaxDegreeOfParallelism to 1.

可以使用这些设置来确保函数在单个实例上作为单一实例运行。You can use these settings to ensure that your function runs as a singleton on a single instance. 若要确保在 Web 应用横向扩展到多个实例时只运行函数的单个实例,请对该函数应用侦听器级别的单一实例锁 ([Singleton(Mode = SingletonMode.Listener)])。To ensure that only a single instance of the function is running when the web app scales out to multiple instances, apply a listener-level singleton lock on the function ([Singleton(Mode = SingletonMode.Listener)]). 启动 JobHost 时获取侦听器锁。Listener locks are acquired when the JobHost starts. 如果三个横向扩展的实例全部同时启动,只有其中的一个实例获取该锁,并且只有一个侦听器启动。If three scaled-out instances all start at the same time, only one of the instances acquires the lock and only one listener starts.

范围值Scope values

可以在单一实例中指定一个范围表达式/值。 You can specify a scope expression/value on a singleton. 表达式/值可确保特定范围内的所有函数执行都将序列化。The expression/value ensures that all executions of the function at a specific scope will be serialized. 以这种方式实现更细化的锁定可以为函数提供一定程度的并行度,同时根据你的需求串行化其他调用。Implementing more granular locking in this way can allow for some level of parallelism for your function while serializing other invocations as dictated by your requirements. 例如,在以下代码中,范围表达式将绑定到传入消息的 Region 值。For example, in the following code, the scope expression binds to the Region value of the incoming message. 如果队列分别在区域 East、East 和 West 中包含 3 条消息,则区域为“East”的消息将串行运行,而区域为 West 的消息将与 East 中的这些消息并行运行。When the queue contains three messages in regions East, East, and West respectively, the messages that have region East are run serially while the message with region West is run in parallel with those in East.

[Singleton("{Region}")]
public static async Task ProcessWorkItem([QueueTrigger("workitems")] WorkItem workItem)
{
     // Process the work item.
}

public class WorkItem
{
     public int ID { get; set; }
     public string Region { get; set; }
     public int Category { get; set; }
     public string Description { get; set; }
}

SingletonScope.HostSingletonScope.Host

锁的默认范围为 SingletonScope.Function,这意味着,锁范围(Blob 租约路径)已绑定到完全限定的函数名称。The default scope for a lock is SingletonScope.Function, meaning the lock scope (the blob lease path) is tied to the fully qualified function name. 若要跨函数锁定,请指定 SingletonScope.Host,并使用在不想要同时运行的所有函数中相同的范围 ID 名称。To lock across functions, specify SingletonScope.Host and use a scope ID name that's the same across all functions that you don't want to run simultaneously. 在以下示例中,每次只会运行 AddItemRemoveItem 的一个实例:In the following example, only one instance of AddItem or RemoveItem runs at a time:

[Singleton("ItemsLock", SingletonScope.Host)]
public static void AddItem([QueueTrigger("add-item")] string message)
{
     // Perform the add operation.
}

[Singleton("ItemsLock", SingletonScope.Host)]
public static void RemoveItem([QueueTrigger("remove-item")] string message)
{
     // Perform the remove operation.
}

查看租约 BlobViewing lease blobs

WebJobs SDK 在幕后使用 Azure Blob 租约来实现分布式锁定。The WebJobs SDK uses Azure blob leases under the covers to implement distributed locking. 可以在 AzureWebJobsStorage 存储帐户的 azure-webjobs-host 容器中的路径“locks”下面找到单一实例使用的租约 Blob。The lease blobs used by Singleton can be found in the azure-webjobs-host container in the AzureWebJobsStorage storage account under the path "locks". 例如,前面演示的第一个 ProcessImage 示例的租约 Blob 路径可能是 locks/061851c758f04938a4426aa9ab3869c0/WebJobs.Functions.ProcessImageFor example, the lease blob path for the first ProcessImage example shown earlier might be locks/061851c758f04938a4426aa9ab3869c0/WebJobs.Functions.ProcessImage. 所有路径包含 JobHost ID,在本例中为 061851c758f04938a4426aa9ab3869c0。All paths include the JobHost ID, in this case 061851c758f04938a4426aa9ab3869c0.

异步函数Async functions

有关如何编写异步函数代码的信息,请参阅 Azure Functions 文档For information about how to code async functions, see the Azure Functions documentation.

取消令牌Cancellation tokens

有关如何处理取消令牌的信息,请参阅有关取消令牌和正常关闭的 Azure Functions 文档。For information about how to handle cancellation tokens, see the Azure Functions documentation on cancellation tokens and graceful shutdown.

多个实例Multiple instances

如果 Web 应用在多个实例上运行,则会有一个连续的 WebJob 在每个实例上运行,并侦听触发器和调用函数。If your web app runs on multiple instances, a continuous WebJob runs on each instance, listening for triggers and calling functions. 各种触发器绑定旨在以协作方式有效分担各个实例上的工作,以便横向扩展到多个实例后可以处理更多的负载。The various trigger bindings are designed to efficiently share work collaboratively across instances, so that scaling out to more instances allows you to handle more load.

队列和 Blob 触发器自动阻止函数多次处理队列消息或 Blob;函数不需要是幂等的。The queue and blob triggers automatically prevent a function from processing a queue message or blob more than once; functions don't have to be idempotent.

计时器触发器会自动确保只会运行计时器的一个实例,因此,在给定的计划时间,不会运行多个函数实例。The timer trigger automatically ensures that only one instance of the timer runs, so you don't get more than one function instance running at a given scheduled time.

如果要确保即使有多个主机 Web 应用的实例,也只有一个函数实例运行,可以使用 Singleton 特性。If you want to ensure that only one instance of a function runs even when there are multiple instances of the host web app, you can use the Singleton attribute.

筛选器Filters

通过函数筛选器(预览版)可以使用自己的逻辑自定义 WebJobs 执行管道。Function Filters (preview) provide a way to customize the WebJobs execution pipeline with your own logic. 筛选器类似于 ASP.NET Core 筛选器Filters are similar to ASP.NET Core filters. 可将其实现为应用到函数或类的声明性特性。You can implement them as declarative attributes that are applied to your functions or classes. 有关详细信息,请参阅函数筛选器For more information, see Function Filters.

日志记录和监视Logging and monitoring

我们建议使用针对 ASP.NET 开发的日志记录框架。We recommend the logging framework that was developed for ASP.NET. 入门文章中介绍了其用法。The Get started article shows how to use it.

日志筛选Log filtering

ILogger 实例创建的每个日志都包含关联的 CategoryLevelEvery log created by an ILogger instance has an associated Category and Level. LogLevel 是一个枚举,整数代码指示相对重要性:LogLevel is an enumeration, and the integer code indicates relative importance:

LogLevelLogLevel 代码Code
跟踪Trace 00
调试Debug 11
信息Information 22
警告Warning 33
错误Error 44
关键Critical 55
None 66

可以将每个类别单独筛选为特定的 LogLevelYou can independently filter each category to a particular LogLevel. 例如,你可能想要查看有关 Blob 触发器处理的所有日志,但对于其他任何操作,只想查看 Error 和更高级别的日志。For example, you might want to see all logs for blob trigger processing but only Error and higher for everything else.

版本 3.xVersion 3.x

版本 3.x 的 SDK 依赖于 .NET Core 内置的筛选。Version 3.x of the SDK relies on the filtering built into .NET Core. 使用 LogCategories 类,可以为特定函数、触发器或用户定义类别。The LogCategories class lets you define categories for specific functions, triggers, or users. 它还能为特定主机状态(例如,StartupResults)定义筛选器。It also defines filters for specific host states, like Startup and Results. 这样就可以微调日志记录输出。This enables you to fine-tune the logging output. 如果在定义类别中未找到任何匹配项,筛选器在决定是否筛选消息时会回退到 Default 值。If no match is found within the defined categories, the filter falls back to the Default value when deciding whether to filter the message.

LogCategories 需要以下 using 语句:LogCategories requires the following using statement:

using Microsoft.Azure.WebJobs.Logging; 

以下示例构造的筛选器默认会筛选 Warning 级别的所有日志。The following example constructs a filter that, by default, filters all logs at the Warning level. Functionresults类别(等效于版本 2.x 中的 Host.Results)在 Error 级别进行筛选。The Function and results categories (equivalent to Host.Results in version 2.x) are filtered at the Error level. 筛选器将当前类别与 LogCategories 实例中所有已注册的级别进行比较,并选择最长匹配项。The filter compares the current category to all registered levels in the LogCategories instance and chooses the longest match. 这意味着,为 Host.Triggers 注册的 Debug 级别将匹配 Host.Triggers.QueueHost.Triggers.BlobThis means that the Debug level registered for Host.Triggers matches Host.Triggers.Queue or Host.Triggers.Blob. 这样,便可以控制更广泛的类别,而无需添加每个类别。This allows you to control broader categories without needing to add each one.

static async Task Main(string[] args)
{
    var builder = new HostBuilder();
    builder.ConfigureWebJobs(b =>
    {
        b.AddAzureStorageCoreServices();
    });
    builder.ConfigureLogging(logging =>
            {
                logging.SetMinimumLevel(LogLevel.Warning);
                logging.AddFilter("Function", LogLevel.Error);
                logging.AddFilter(LogCategories.CreateFunctionCategory("MySpecificFunctionName"),
                    LogLevel.Debug);
                logging.AddFilter(LogCategories.Results, LogLevel.Error);
                logging.AddFilter("Host.Triggers", LogLevel.Debug);
            });
    var host = builder.Build();
    using (host)
    {
        await host.RunAsync();
    }
}

版本 2.xVersion 2.x

在版本 2.x 的 SDK 中,LogCategoryFilter 类用于控制筛选。In version 2.x of the SDK, you use the LogCategoryFilter class to control filtering. LogCategoryFilter 包含初始值为 InformationDefault 属性,这意味着,将会记录级别为 InformationWarningErrorCritical 的所有消息,但会筛选掉级别为 DebugTrace 的所有消息。The LogCategoryFilter has a Default property with an initial value of Information, meaning that any messages at the Information, Warning, Error, or Critical levels are logged, but any messages at the Debug or Trace levels are filtered away.

与版本 3.x 中的 LogCategories 一样,使用 CategoryLevels 属性可以指定特定类别的日志级别,以便能够微调日志记录输出。As with LogCategories in version 3.x, the CategoryLevels property allows you to specify log levels for specific categories so you can fine-tune the logging output. 如果在 CategoryLevels 字典中未找到任何匹配项,筛选器在决定是否筛选消息时会回退到 Default 值。If no match is found within the CategoryLevels dictionary, the filter falls back to the Default value when deciding whether to filter the message.

以下示例构造的筛选器默认会筛选 Warning 级别的所有日志。The following example constructs a filter that by default filters all logs at the Warning level. FunctionHost.Results 类别在 Error 级别进行筛选。The Function and Host.Results categories are filtered at the Error level. LogCategoryFilter 将当前类别与所有已注册的 CategoryLevels 进行比较,并选择最长匹配项。The LogCategoryFilter compares the current category to all registered CategoryLevels and chooses the longest match. 因此,为 Host.Triggers 注册的 Debug 级别将匹配 Host.Triggers.QueueHost.Triggers.BlobSo the Debug level registered for Host.Triggers will match Host.Triggers.Queue or Host.Triggers.Blob. 这样,便可以控制更广泛的类别,而无需添加每个类别。This allows you to control broader categories without needing to add each one.

var filter = new LogCategoryFilter();
filter.DefaultLevel = LogLevel.Warning;
filter.CategoryLevels[LogCategories.Function] = LogLevel.Error;
filter.CategoryLevels[LogCategories.Results] = LogLevel.Error;
filter.CategoryLevels["Host.Triggers"] = LogLevel.Debug;

config.LoggerFactory = new LoggerFactory()
    .AddApplicationInsights(instrumentationKey, filter.Filter)
    .AddConsole(filter.Filter);

Application Insights 的自定义遥测Custom telemetry for Application Insights

Application Insights 实现自定义遥测的过程取决于 SDK 版本。The process for implementing custom telemetry for Application Insights depends on the SDK version. 要了解如何配置 Application Insights,请参阅添加 Application Insights 日志记录To learn how to configure Application Insights, see Add Application Insights logging.

版本 3.xVersion 3.x

由于 WebJobs SDK 的版本 3.x 依赖于 .NET Core 通用主机,因此不再提供自定义遥测工厂。Because version 3.x of the WebJobs SDK relies on the .NET Core generic host, a custom telemetry factory is no longer provided. 但可以使用依赖关系注入将自定义遥测添加到管道。But you can add custom telemetry to the pipeline by using dependency injection. 本部分中的示例要求使用下列 using 语句:The examples in this section require the following using statements:

using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.Channel;

使用以下 ITelemetryInitializer 的自定义实现,可向默认的 TelemetryConfiguration 添加自己的 ITelemetryThe following custom implementation of ITelemetryInitializer lets you add your own ITelemetry to the default TelemetryConfiguration.

internal class CustomTelemetryInitializer : ITelemetryInitializer
{
    public void Initialize(ITelemetry telemetry)
    {
        // Do something with telemetry.
    }
}

在生成器中调用 ConfigureServices,以将自定义 ITelemetryInitializer 添加到管道。Call ConfigureServices in the builder to add your custom ITelemetryInitializer to the pipeline.

static void Main()
{
    var builder = new HostBuilder();
    builder.ConfigureWebJobs(b =>
    {
        b.AddAzureStorageCoreServices();
    });
    builder.ConfigureLogging((context, b) =>
    {
        // Add logging providers.
        b.AddConsole();

        // If this key exists in any config, use it to enable Application Insights.
        string appInsightsKey = context.Configuration["APPINSIGHTS_INSTRUMENTATIONKEY"];
        if (!string.IsNullOrEmpty(appInsightsKey))
        {
            // This uses the options callback to explicitly set the instrumentation key.
            b.AddApplicationInsights(o => o.InstrumentationKey = appInsightsKey);
        }
    });
    builder.ConfigureServices(services =>
        {
            services.AddSingleton<ITelemetryInitializer, CustomTelemetryInitializer>();
        });
    var host = builder.Build();
    using (host)
    {

        host.Run();
    }
}

构造 TelemetryConfiguration 时,将添加所有已注册类型的 ITelemetryInitializerWhen the TelemetryConfiguration is constructed, all registered types of ITelemetryInitializer are included. 若要了解详细信息,请参阅用于处理自定义事件和指标的 Application Insights APITo learn more, see Application Insights API for custom events and metrics.

在版本 3.x 中,主机停止时无需刷新 TelemetryClientIn version 3.x, you no longer have to flush the TelemetryClient when the host stops. .NET Core 依赖关系注入系统将自动释放已注册 ApplicationInsightsLoggerProvider,可刷新 TelemetryClientThe .NET Core dependency injection system automatically disposes of the registered ApplicationInsightsLoggerProvider, which flushes the TelemetryClient.

版本 2.xVersion 2.x

在版本 2.x 中,Application Insights 提供程序为 WebJobs SDK 在内部创建的 TelemetryClient 使用 ServerTelemetryChannelIn version 2.x, the TelemetryClient created internally by the Application Insights provider for the WebJobs SDK uses ServerTelemetryChannel. 当 Application Insights 终结点时不可用或限制传入请求时,此通道会在 Web 应用的文件系统中保存请求,并稍后提交这些请求When the Application Insights endpoint is unavailable or throttling incoming requests, this channel saves requests in the web app's file system and resubmits them later.

TelemetryClient 是实现 ITelemetryClientFactory 的类创建的。The TelemetryClient is created by a class that implements ITelemetryClientFactory. 默认为 DefaultTelemetryClientFactoryBy default, this is the DefaultTelemetryClientFactory.

若要修改 Application Insights 管道的任何组成部分,可以提供自己的 ITelemetryClientFactory,而主机会使用你的类来构造 TelemetryClientIf you want to modify any part of the Application Insights pipeline, you can supply your own ITelemetryClientFactory, and the host will use your class to construct a TelemetryClient. 例如,此代码会重写 DefaultTelemetryClientFactory 以修改 ServerTelemetryChannel 的属性:For example, this code overrides DefaultTelemetryClientFactory to modify a property of ServerTelemetryChannel:

private class CustomTelemetryClientFactory : DefaultTelemetryClientFactory
{
    public CustomTelemetryClientFactory(string instrumentationKey, Func<string, LogLevel, bool> filter)
        : base(instrumentationKey, new SamplingPercentageEstimatorSettings(), filter)
    {
    }

    protected override ITelemetryChannel CreateTelemetryChannel()
    {
        ServerTelemetryChannel channel = new ServerTelemetryChannel();

        // Change the default from 30 seconds to 15 seconds.
        channel.MaxTelemetryBufferDelay = TimeSpan.FromSeconds(15);

        return channel;
    }
}

SamplingPercentageEstimatorSettings 对象配置自适应采样The SamplingPercentageEstimatorSettings object configures adaptive sampling. 这意味着,在某些大容量方案中,Applications Insights 会向服务器发送选定的遥测数据子集。This means that in certain high-volume scenarios, Applications Insights sends a selected subset of telemetry data to the server.

创建遥测工厂后,可将其传入 Application Insights 日志记录提供程序:After you create the telemetry factory, you pass it in to the Application Insights logging provider:

var clientFactory = new CustomTelemetryClientFactory(instrumentationKey, filter.Filter);

config.LoggerFactory = new LoggerFactory()
    .AddApplicationInsights(clientFactory);

后续步骤Next steps

本文提供的代码片段演示了如何处理 WebJobs SDK 的常用方案。This article has provided code snippets that show how to handle common scenarios for working with the WebJobs SDK. 有关完整示例,请参阅 azure-webjobs-sdk-samplesFor complete samples, see azure-webjobs-sdk-samples.