有关在 Azure 中的 .NET 5.0 上运行函数的指南Guide for running functions on .NET 5.0 in Azure

本文介绍如何使用 C# 开发 .NET 隔离进程函数,这些函数在 Azure Functions 中的进程外运行。This article is an introduction to using C# to develop .NET isolated process functions, which run out-of-process in Azure Functions. 通过进程外的运行,可将函数代码与 Azure Functions 运行时分离开来。Running out-of-process lets you decouple your function code from the Azure Functions runtime. 此外,还可以创建并运行面向当前 .NET 5.0 版本的函数。It also provides a way for you to create and run functions that target the current .NET 5.0 release.

入门Getting started 概念Concepts 示例Samples

如果你不需要支持 .NET 5.0 或者在进程外运行函数,可以改而开发 C# 类库函数If you don't need to support .NET 5.0 or run your functions out-of-process, you might want to instead develop C# class library functions.

为何使用 .NET 隔离进程?Why .NET isolated process?

过去,Azure Functions 仅支持 .NET 函数的紧密集成模式,这种模式在主机所用的同一进程中作为类库运行。Previously Azure Functions has only supported a tightly integrated mode for .NET functions, which run as a class library in the same process as the host. 此模式在主机进程与函数之间提供深度集成。This mode provides deep integration between the host process and the functions. 例如,.NET 类库函数可以共享绑定 API 和类型。For example, .NET class library functions can share binding APIs and types. 但是,这种集成还要求在主机进程与 .NET 函数之间实现更紧密的耦合。However, this integration also requires a tighter coupling between the host process and the .NET function. 例如,在进程内运行的 .NET 函数需要在 Functions 运行时所用的同一 .NET 版本上运行。For example, .NET functions running in-process are required to run on the same version of .NET as the Functions runtime. 为了能够摆脱这些约束顺利运行,现在可以选择在隔离的进程中运行。To enable you to run outside these constraints, you can now choose to run in an isolated process. 借助这种进程隔离,还可以开发使用当前 .NET 版本(例如 .NET 5.0)且不受 Functions 运行时原生支持的函数。This process isolation also lets you develop functions that use current .NET releases (such as .NET 5.0), not natively supported by the Functions runtime.

由于这些函数在独立的进程中运行,.NET 隔离的函数应用与 .NET 类库函数应用之间存在一些特性和功能差异Because these functions run in a separate process, there are some feature and functionality differences between .NET isolated function apps and .NET class library function apps.

在进程外运行的优势Benefits of running out-of-process

在进程外运行时,.NET 函数可利用以下优势:When running out-of-process, your .NET functions can take advantage of the following benefits:

  • 减少冲突:由于函数在独立的进程中运行,因此应用中使用的程序集不会与主机进程所用的相同程序集的不同版本发生冲突。Fewer conflicts: because the functions run in a separate process, assemblies used in your app won't conflict with different version of the same assemblies used by the host process.
  • 全面控制进程:可以控制应用的启动,并可控制所用的配置和启动的中间件。Full control of the process: you control the start-up of the app and can control the configurations used and the middleware started.
  • 依赖项注入:由于可以全面控制进程,因此可以使用当前的 .NET 依赖项注入行为,并将中间件整合到函数应用中。Dependency injection: because you have full control of the process, you can use current .NET behaviors for dependency injection and incorporating middleware into your function app.

支持的版本Supported versions

目前支持进程外运行的 .NET 版本只有 .NET 5.0。The only version of .NET that is currently supported to run out-of-process is .NET 5.0.

.NET 隔离项目.NET isolated project

简单而言,.NET 隔离函数项目是一个面向 .NET 5.0 的 .NET 控制台应用项目。A .NET isolated function project is basically a .NET console app project that targets .NET 5.0. 下面是任何 .NET 隔离项目中所需的基本文件:The following are the basic files required in any .NET isolated project:

  • host.json 文件。host.json file.
  • local.settings.json 文件。local.settings.json file.
  • C# 项目文件 (.csproj),用于定义项目和依赖项。C# project file (.csproj) that defines the project and dependencies.
  • Program.cs 文件,应用的入口点。Program.cs file that's the entry point for the app.

包引用Package references

在进程外运行时,.NET 项目将使用一组唯一的包,这些包实现核心功能和绑定扩展。When running out-of-process, your .NET project uses a unique set of packages, which implement both core functionality and binding extensions.

核心包Core packages

需要使用以下包在隔离的进程中运行 .NET 函数:The following packages are required to run your .NET functions in an isolated process:

扩展包Extension packages

由于在 .NET 隔离进程中运行的函数使用不同的绑定类型,因此它们需要一组唯一的绑定扩展包。Because functions that run in a .NET isolated process use different binding types, they require a unique set of binding extension packages.

可以在 Microsoft.Azure.Functions.Worker.Extensions 下找到这些扩展包。You'll find these extension packages under Microsoft.Azure.Functions.Worker.Extensions.

启动和配置Start-up and configuration

使用 .NET 隔离函数时,可以访问函数应用的启动代码(通常在 Program.cs 中)。When using .NET isolated functions, you have access to the start-up of your function app, which is usually in Program.cs. 你需要负责创建并启动自己的主机实例。You're responsible for creating and starting your own host instance. 因此,你还可以直接访问应用的配置管道。As such, you also have direct access to the configuration pipeline for your app. 在进程外运行时,注入依赖项和运行中间件的操作要容易得多。When running out-of-process, you can much more easily add configurations, inject dependencies, and run your own middleware.

以下代码显示了 HostBuilder 管道的示例:The following code shows an example of a HostBuilder pipeline:

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace FunctionApp
{
    class Program
    {
        static async Task Main(string[] args)
        {
// #if DEBUG
//          Debugger.Launch();
// #endif
            //<docsnippet_startup>
            var host = new HostBuilder()
                //<docsnippet_configure_defaults>
                .ConfigureFunctionsWorkerDefaults()
                //</docsnippet_configure_defaults>
                //<docsnippet_dependency_injection>
                .ConfigureServices(s =>
                {
                    s.AddSingleton<IHttpResponderService, DefaultHttpResponderService>();
                })
                //</docsnippet_dependency_injection>
                .Build();
            //</docsnippet_startup>

            //<docsnippet_host_run>
            await host.RunAsync();
            //</docsnippet_host_run>
        }
    }
}

HostBuilder 用于生成并返回已完全初始化的 IHost 实例,该实例以异步方式运行以启动函数应用。A HostBuilder is used to build and return a fully initialized IHost instance, which you run asynchronously to start your function app.

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace FunctionApp
{
    class Program
    {
        static async Task Main(string[] args)
        {
// #if DEBUG
//          Debugger.Launch();
// #endif
            //<docsnippet_startup>
            var host = new HostBuilder()
                //<docsnippet_configure_defaults>
                .ConfigureFunctionsWorkerDefaults()
                //</docsnippet_configure_defaults>
                //<docsnippet_dependency_injection>
                .ConfigureServices(s =>
                {
                    s.AddSingleton<IHttpResponderService, DefaultHttpResponderService>();
                })
                //</docsnippet_dependency_injection>
                .Build();
            //</docsnippet_startup>

            //<docsnippet_host_run>
            await host.RunAsync();
            //</docsnippet_host_run>
        }
    }
}

配置Configuration

ConfigureFunctionsWorkerDefaults 方法用于添加函数应用在进程外运行所需的设置,包括以下功能:The ConfigureFunctionsWorkerDefaults method is used to add the settings required for the function app to run out-of-process, which includes the following functionality:

  • 转换器的默认设置。Default set of converters.
  • 设置默认 JsonSerializerOptions 以忽略属性名称大小写。Set the default JsonSerializerOptions to ignore casing on property names.
  • 与 Azure Functions 日志记录集成。Integrate with Azure Functions logging.
  • 输出绑定中间件和功能。Output binding middleware and features.
  • 函数执行中间件。Function execution middleware.
  • 默认的 gRPC 支持。Default gRPC support.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace FunctionApp
{
    class Program
    {
        static async Task Main(string[] args)
        {
// #if DEBUG
//          Debugger.Launch();
// #endif
            //<docsnippet_startup>
            var host = new HostBuilder()
                //<docsnippet_configure_defaults>
                .ConfigureFunctionsWorkerDefaults()
                //</docsnippet_configure_defaults>
                //<docsnippet_dependency_injection>
                .ConfigureServices(s =>
                {
                    s.AddSingleton<IHttpResponderService, DefaultHttpResponderService>();
                })
                //</docsnippet_dependency_injection>
                .Build();
            //</docsnippet_startup>

            //<docsnippet_host_run>
            await host.RunAsync();
            //</docsnippet_host_run>
        }
    }
}

能够访问主机生成器管道意味着还可以在初始化期间设置任何特定于应用的配置。Having access to the host builder pipeline means that you can also set any app-specific configurations during initialization. 可以一次或多次调用HostBuilder 中的 ConfigureAppConfiguration 方法来添加函数应用所需的配置。You can call the ConfigureAppConfiguration method on HostBuilder one or more times to add the configurations required by your function app. 若要详细了解应用配置,请参阅 ASP.NET Core 中的配置To learn more about app configuration, see Configuration in ASP.NET Core.

这些配置将应用到在独立进程中运行的函数应用。These configurations apply to your function app running in a separate process. 若要更改 Functions 主机或触发器以及绑定配置,仍需使用 host.json 文件To make changes to the functions host or trigger and binding configuration, you'll still need to use the host.json file.

依赖关系注入Dependency injection

与 .NET 类库相比,依赖项注入已得到简化。Dependency injection is simplified, compared to .NET class libraries. 不必创建启动类来注册服务,而只需在主机生成器中调用 ConfigureServices,并使用 IServiceCollection 中的扩展方法来注入特定的服务。Rather than having to create a startup class to register services, you just have to call ConfigureServices on the host builder and use the extension methods on IServiceCollection to inject specific services.

以下示例注入单一实例服务依赖项:The following example injects a singleton service dependency:

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace FunctionApp
{
    class Program
    {
        static async Task Main(string[] args)
        {
// #if DEBUG
//          Debugger.Launch();
// #endif
            //<docsnippet_startup>
            var host = new HostBuilder()
                //<docsnippet_configure_defaults>
                .ConfigureFunctionsWorkerDefaults()
                //</docsnippet_configure_defaults>
                //<docsnippet_dependency_injection>
                .ConfigureServices(s =>
                {
                    s.AddSingleton<IHttpResponderService, DefaultHttpResponderService>();
                })
                //</docsnippet_dependency_injection>
                .Build();
            //</docsnippet_startup>

            //<docsnippet_host_run>
            await host.RunAsync();
            //</docsnippet_host_run>
        }
    }
}

有关详细信息,请参阅 ASP.NET Core 中的依赖项注入To learn more, see Dependency injection in ASP.NET Core.

中间件Middleware

.NET 隔离进程还支持中间件注册,这同样是使用与 ASP.NET 中类似的模型实现的。.NET isolated also supports middleware registration, again by using a model similar to what exists in ASP.NET. 使用此模型可以在执行函数之前和之后将逻辑注入到调用管道中。This model gives you the ability to inject logic into the invocation pipeline, and before and after functions execute.

ConfigureFunctionsWorkerDefaults 扩展方法具有一个重载,可让你注册自己的中间件,如以下示例中所示。The ConfigureFunctionsWorkerDefaults extension method has an overload that lets you register your own middleware, as you can see in the following example.

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace CustomMiddleware
{
    public class Program
    {
        public static void Main()
        {
            //<docsnippet_middleware_register>
            var host = new HostBuilder()
                .ConfigureFunctionsWorkerDefaults(workerApplication =>
                {
                    // Register our custom middleware with the worker
                    workerApplication.UseMiddleware<MyCustomMiddleware>();
                })
                .Build();
            //</docsnippet_middleware_register>

            host.Run();
        }
    }
}

有关在函数应用中使用自定义中间件的更完整示例,请参阅自定义中间件参考示例For a more complete example of using custom middleware in your function app, see the custom middleware reference sample.

执行上下文Execution context

.NET 隔离进程将 FunctionContext 对象传递给函数方法。.NET isolated passes a FunctionContext object to your function methods. 使用此对象可以通过调用 GetLogger 方法并提供 categoryName 字符串,来获取要写入到日志的 ILogger 实例。This object lets you get an ILogger instance to write to the logs by calling the GetLogger method and supplying a categoryName string. 有关详细信息,请参阅日志记录To learn more, see Logging.

绑定Bindings

绑定是通过在方法、参数和返回类型中使用特性定义的。Bindings are defined by using attributes on methods, parameters, and return types. 函数方法是包含 Function 特性以及一个应用于输入参数的触发器特性的方法,如以下示例中所示:A function method is a method with a Function attribute and a trigger attribute applied to an input parameter, as shown in the following example:

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;

namespace SampleApp
{
    public static class QueueFunction
    {
        //<docsnippet_queue_output_binding>
        //<docsnippet_queue_trigger>
        [Function("QueueFunction")]
        [QueueOutput("functionstesting2")]
        public static string Run([QueueTrigger("functionstesting2")] Book myQueueItem,
            FunctionContext context)
        //</docsnippet_queue_trigger>
        {
            var logger = context.GetLogger("QueueFunction");
            logger.LogInformation($"Book name = {myQueueItem.Name}");

            // Queue Output
            return "queue message";
        }
        //</docsnippet_queue_output_binding>
    }

    public class Book
    {
        public string Name { get; set; }

        public string Id { get; set; }
    }
}

触发器属性指定触发器类型并将输入数据绑定到一个方法参数。The trigger attribute specifies the trigger type and binds input data to a method parameter. 以上示例函数将由一条队列消息触发,队列消息将传递给方法中的 myQueueItem 参数。The previous example function is triggered by a queue message, and the queue message is passed to the method in the myQueueItem parameter.

Function 属性将该方法标记为函数入口点。The Function attribute marks the method as a function entry point. 该名称在项目中必须是唯一的,以字母开头,并且只包含字母、数字、_-,长度不得超过 127 个字符。The name must be unique within a project, start with a letter and only contain letters, numbers, _, and -, up to 127 characters in length. 项目模板通常创建一个名为 Run 的方法,但方法名称可以是任何有效的 C# 方法名称。Project templates often create a method named Run, but the method name can be any valid C# method name.

由于 .NET 隔离项目在独立的工作进程中运行,因此绑定无法利用丰富的绑定类,例如 ICollector<T>IAsyncCollector<T>CloudBlockBlobBecause .NET isolated projects run in a separate worker process, bindings can't take advantage of rich binding classes, such as ICollector<T>, IAsyncCollector<T>, and CloudBlockBlob. 此外,不直接支持继承自底层服务 SDK 的类型,例如 DocumentClientBrokeredMessageThere's also no direct support for types inherited from underlying service SDKs, such as DocumentClient and BrokeredMessage. 绑定依赖于字符串、数组和可序列化类型,例如普通旧类对象 (POCO)。Instead, bindings rely on strings, arrays, and serializable types, such as plain old class objects (POCOs).

对于 HTTP 触发器,必须使用 HttpRequestDataHttpResponseData 来访问请求与响应数据。For HTTP triggers, you must use HttpRequestData and HttpResponseData to access the request and response data. 这是因为,在进程外运行时,无法访问原始 HTTP 请求和响应对象。This is because you don't have access to the original HTTP request and response objects when running out-of-process.

有关在进程外运行时使用触发器和绑定的一组完整参考示例,请参阅绑定扩展参考示例For a complete set of reference samples for using triggers and bindings when running out-of-process, see the binding extensions reference sample.

输入绑定Input bindings

一个函数可以有零个或多个可向函数传递数据的输入绑定。A function can have zero or more input bindings that can pass data to a function. 与触发器一样,输入绑定是通过向输入参数应用绑定特性来定义的。Like triggers, input bindings are defined by applying a binding attribute to an input parameter. 执行函数时,运行时将尝试获取绑定中指定的数据。When the function executes, the runtime tries to get data specified in the binding. 请求的数据通常依赖于触发器使用绑定参数提供的信息。The data being requested is often dependent on information provided by the trigger using binding parameters.

输出绑定Output bindings

若要写入到输出绑定,必须将输出绑定特性应用到函数方法,该方法定义了如何写入到绑定的服务。To write to an output binding, you must apply an output binding attribute to the function method, which defined how to write to the bound service. 该方法返回的值将写入到输出绑定。The value returned by the method is written to the output binding. 例如,以下示例使用输出绑定将一个字符串值写入到名为 functiontesting2 的消息队列:For example, the following example writes a string value to a message queue named functiontesting2 by using an output binding:

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;

namespace SampleApp
{
    public static class QueueFunction
    {
        //<docsnippet_queue_output_binding>
        //<docsnippet_queue_trigger>
        [Function("QueueFunction")]
        [QueueOutput("functionstesting2")]
        public static string Run([QueueTrigger("functionstesting2")] Book myQueueItem,
            FunctionContext context)
        //</docsnippet_queue_trigger>
        {
            var logger = context.GetLogger("QueueFunction");
            logger.LogInformation($"Book name = {myQueueItem.Name}");

            // Queue Output
            return "queue message";
        }
        //</docsnippet_queue_output_binding>
    }

    public class Book
    {
        public string Name { get; set; }

        public string Id { get; set; }
    }
}

多个输出绑定Multiple output bindings

写入到输出绑定的数据始终是函数的返回值。The data written to an output binding is always the return value of the function. 如果需要写入到多个输出绑定,必须创建自定义返回类型。If you need to write to more than one output binding, you must create a custom return type. 在此返回类型中,必须已将输出绑定特性应用到类的一个或多个属性。This return type must have the output binding attribute applied to one or more properties of the class. 以下示例写入到 HTTP 响应和队列输出绑定:The following example writes to both an HTTP response and a queue output binding:

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System.Net;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;

namespace SampleApp
{
    /// <summary>
    /// This class specifies output bindings in the properties of <see cref="MyOutputType"/>.
    /// <see cref="MyOutputType"/> defines a Queue output binding, and an Http Response property.
    /// By default, a property of type <see cref="HttpResponseData"/> in the return type of the function
    /// is treated as an Http output binding. This property can be used to provide a response to the Http trigger.
    /// </summary>
    //<docsnippet_multiple_outputs>
    public static class MultiOutput
    {
        [Function("MultiOutput")]
        public static MyOutputType Run([HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequestData req,
            FunctionContext context)
        {
            var response = req.CreateResponse(HttpStatusCode.OK);
            response.WriteString("Success!");

            string myQueueOutput = "some output";

            return new MyOutputType()
            {
                Name = myQueueOutput,
                HttpReponse = response
            };
        }
    }

    public class MyOutputType
    {
        [QueueOutput("myQueue")]
        public string Name { get; set; }

        public HttpResponseData HttpReponse { get; set; }
    }
    //</docsnippet_multiple_outputs>
}

HTTP 触发器HTTP trigger

HTTP 触发器将传入的 HTTP 请求消息转换为要传递给函数的 HttpRequestData 对象。HTTP triggers translates the incoming HTTP request message into an HttpRequestData object that is passed to the function. 此对象提供请求中的数据,包括 HeadersCookiesIdentitiesURL 和可选消息 BodyThis object provides data from the request, including Headers, Cookies, Identities, URL, and optional a message Body. 此对象是 HTTP 请求对象的表示形式,而不是请求本身。This object is a representation of the HTTP request object and not the request itself.

同样,函数返回一个 [HttpReponseData] 对象,该对象提供用于创建 HTTP 响应的数据,包括消息 StatusCodeHeaders 和可选消息 BodyLikewise, the function returns an [HttpReponseData] object, which provides data used to create the HTTP response, including message StatusCode, Headers, and optionally a message Body.

以下代码是一个 HTTP 触发器The following code is an HTTP trigger

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System.Net;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;

namespace SampleApp
{
    public static class HttpFunction
    {
        //<docsnippet_http_trigger>
        [Function("HttpFunction")]
        public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequestData req,
            FunctionContext executionContext)
        {
            //<docsnippet_logging>
            var logger = executionContext.GetLogger("HttpFunction");
            logger.LogInformation("message logged");
            //</docsnippet_logging>

            var response = req.CreateResponse(HttpStatusCode.OK);
            response.Headers.Add("Date", "Mon, 18 Jul 2016 16:06:00 GMT");
            response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
            
            response.WriteString("Welcome to .NET 5!!");

            return response;
        }
        //</docsnippet_http_trigger>
    }
}

日志记录Logging

在 .NET 隔离进程中,可以使用 ILogger 实例写入日志,该实例是从传递给函数的 FunctionContext 对象获取的。In .NET isolated, you can write to logs by using an ILogger instance obtained from a FunctionContext object passed to your function. 调用 GetLogger 方法并传递一个字符串值,该值是在其中写入日志的类别的名称。Call the GetLogger method, passing a string value that is the name for the category in which the logs are written. 该类别通常是从中写入日志的特定函数的名称。The category is usually the name of the specific function from which the logs are written. 若要详细了解类别,请参阅有关监视的文章To learn more about categories, see the monitoring article.

以下示例演示如何获取 ILogger 并在函数中写入日志:The following example shows how to get an ILogger and write logs inside a function:

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System.Net;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;

namespace SampleApp
{
    public static class HttpFunction
    {
        //<docsnippet_http_trigger>
        [Function("HttpFunction")]
        public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequestData req,
            FunctionContext executionContext)
        {
            //<docsnippet_logging>
            var logger = executionContext.GetLogger("HttpFunction");
            logger.LogInformation("message logged");
            //</docsnippet_logging>

            var response = req.CreateResponse(HttpStatusCode.OK);
            response.Headers.Add("Date", "Mon, 18 Jul 2016 16:06:00 GMT");
            response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
            
            response.WriteString("Welcome to .NET 5!!");

            return response;
        }
        //</docsnippet_http_trigger>
    }
}

使用 ILogger 的各种方法写入各种日志级别,例如 LogWarningLogErrorUse various methods of ILogger to write various log levels, such as LogWarning or LogError. 若要详细了解日志级别,请参阅有关监视的文章To learn more about log levels, see the monitoring article.

使用依赖项注入时还会提供 ILoggerAn ILogger is also provided when using dependency injection.

与 .NET 类库函数之间的差异Differences with .NET class library functions

本部分介绍 .NET 5.0 进程外运行与 .NET 类库函数进程内运行的当前功能差异和行为差异状态:This section describes the current state of the functional and behavioral differences running on .NET 5.0 out-of-process compared to .NET class library functions running in-process:

功能/行为Feature/behavior 进程内 (.NET Core 3.1)In-process (.NET Core 3.1) 进程外 (.NET 5.0)Out-of-process (.NET 5.0)
.NET 版本.NET versions LTS (.NET Core 3.1)LTS (.NET Core 3.1) 当前版本 (.NET 5.0)Current (.NET 5.0)
核心包Core packages Microsoft.NET.Sdk.FunctionsMicrosoft.NET.Sdk.Functions Microsoft.Azure.Functions.WorkerMicrosoft.Azure.Functions.Worker
Microsoft.Azure.Functions.Worker.SdkMicrosoft.Azure.Functions.Worker.Sdk
绑定扩展包Binding extension packages Microsoft.Azure.WebJobs.Extensions.*Microsoft.Azure.WebJobs.Extensions.* Microsoft.Azure.Functions.Worker.Extensions.*Under Microsoft.Azure.Functions.Worker.Extensions.*
日志记录Logging 传递给函数的 ILoggerILogger passed to the function FunctionContext 获取的 ILoggerILogger obtained from FunctionContext
取消令牌Cancellation tokens 支持Supported 不支持Not supported
输出绑定Output bindings 输出参数Out parameters 返回值Return values
输出绑定类型Output binding types IAsyncCollectorDocumentClientBrokeredMessage 和其他特定于客户端的类型IAsyncCollector, DocumentClient, BrokeredMessage, and other client-specific types 简单类型、JSON 可序列化类型和数组。Simple types, JSON serializable types, and arrays.
多个输出绑定Multiple output bindings 支持Supported 支持Supported
HTTP 触发器HTTP trigger HttpRequest/ObjectResultHttpRequest/ObjectResult HttpRequestData/HttpResponseDataHttpRequestData/HttpResponseData
Durable FunctionsDurable Functions 支持Supported 不支持Not supported
命令性绑定Imperative bindings 支持Supported 不支持Not supported
function.json 项目function.json artifact 已生成Generated 不生成Not generated
ConfigurationConfiguration host.jsonhost.json host.json 和自定义初始化host.json and custom initialization
依赖关系注入Dependency injection 支持Supported 支持Supported
中间件Middleware 不支持Not supported 支持Supported
冷启动时间Cold start times 典型Typical 因为是即时启动,所以时间更长。Longer, because of just-in-time start-up. 在 Linux 而不是 Windows 上运行,以减少潜在的延迟。Run on Linux instead of Windows to reduce potential delays.
ReadyToRunReadyToRun 支持Supported TBDTBD

已知问题Known issues

有关运行 .NET 隔离进程函数时存在的已知问题的解决方法,请参阅此已知问题页For information on workarounds to know issues running .NET isolated process functions, see this known issues page. 若要报告问题,请在此 GitHub 存储库中创建问题To report problems, create an issue in this GitHub repository.

后续步骤Next steps