你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

将 .NET 应用从进程内模型迁移到独立辅助角色模型

重要

对进程内模型的支持将于 2026 年 11 月 10 日结束。 强烈建议按照本文中的说明将应用迁移到独立的辅助角色模型。

本文将引导你完成将 .NET 函数应用程序从进程内模型安全迁移到独立辅助角色模型的过程。 若要了解这些模型之间的大致差异,请参阅执行模式比较

本指南假设你的应用程序在 Functions 运行时版本 4.x 上运行。 否则,应遵循升级主机版本的指南:

浏览这些主机版本迁移指南还可以帮助你迁移到独立的辅助角色模型。

确定要迁移的函数应用

使用以下 Azure PowerShell 脚本,在订阅中生成当前使用进程内模型的函数应用的列表。

该脚本使用 Azure PowerShell 当前配置为使用的订阅。 可以更改订阅,方法是先运行 Set-AzContext -Subscription '<YOUR SUBSCRIPTION ID>' 并将 <YOUR SUBSCRIPTION ID> 替换为要评估的订阅的 ID。

$FunctionApps = Get-AzFunctionApp

$AppInfo = @{}

foreach ($App in $FunctionApps)
{
     if ($App.Runtime -eq 'dotnet')
     {
          $AppInfo.Add($App.Name, $App.Runtime)
     }
}

$AppInfo

选择目标 .NET 版本

在 Functions 运行时版本 4.x 上,.NET 函数应用在使用进程内模型时以 .NET 6 为目标。

迁移函数应用时,你将有机会选择 .NET 的目标版本。 可以将 C# 项目更新到 Functions 版本 4.x 支持的以下 .NET 版本之一:

.NET 版本 .NET 官方支持策略版本类型 Functions 进程模型1,3
.NET 82 LTS 独立工作模型
.NET 7 STS(2024 年 5 月 14 日结束支持) 独立工作模型
.NET 6 LTS(2024 年 11 月 12 日结束支持) 独立工作模型
进程内模型3
.NET Framework 4.8 查看策略 独立工作模型

1独立工作模型支持 .NET 的长期支持 (LTS) 和标准期限支持 (STS),以及 .NET Framework。 而进程内模型仅支持 .NET 的 LTS 版本。 有关两类模型之间完整的特性和功能比较,请参阅进程内和独立工作进程 .NET Azure Functions 之间的差异

2 进程内模型上尚不受支持 .NET8,但在独立工作器模型上可用。 有关 .NET 8 计划的信息,包括进程内模型的未来选项,请参阅 Azure Functions 路线图更新文章

3 对进程内模型的支持于 2026 年 11 月 10 日结束。 有关详细信息,请参阅此支持公告。 为了继续获得完全支持,应将应用迁移到独立的辅助角色模型

提示

我们建议在独立辅助角色模型上升级到 .NET 8。 这提供了从 .NET 到具有最长支持窗口的完全发布版本的快速迁移路径。

本指南未提供适用于 .NET 7 或 .NET 6 的特定示例。 如果需要面向这些版本,可以改编 .NET 8 示例。

准备迁移

如果尚未开始,请使用Azure PowerShell确定需要在当前 Azure 订阅中迁移的应用列表。

在将应用迁移到独立的工作器模型之前,应全面查看本指南的内容,并熟悉独立工作器模型的功能和两个模型之间的差异

若要迁移应用程序,需要:

  1. 完成迁移本地项目中的步骤,将本地项目迁移到独立的工作器模型。
  2. 迁移项目后,使用Azure Functions Core Tools版本 4.x 在本地全面测试应用。
  3. 将 Azure 中的函数应用更新到独立模型。

迁移本地项目

本节概述了为将本地项目移动到独立辅助角色模型,需要对其进行的各种更改。 某些步骤会根据 .NET 的目标版本而更改。 使用选项卡选择与所需版本匹配的说明。 这些步骤假定使用本地 C# 项目,并且如果应用改用 C# 脚本(.csx 文件),则应 先转换为项目模型,然后再继续操作。

提示

如果要迁移到 .NET 的 LTS 或 STS 版本,可使用 .NET 升级助手自动进行以下部分提到的许多更改。

首先,转换项目文件并更新依赖项。 执行此操作时,你将看到项目的生成错误。 在后续步骤中,你将进行相应的更改以消除这些错误。

项目文件

以下示例是在版本 4.x 上使用 .NET 6 的 .csproj 项目文件:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
    <RootNamespace>My.Namespace</RootNamespace>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.1.1" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
</Project>

使用以下过程之一将此 XML 文件更新为在独立辅助角色模型中运行:

这些步骤假定使用本地 C# 项目,并且如果应用改用 C# 脚本(.csx 文件),则应 先转换为项目模型,然后再继续操作。

需要在 .csproj XML 项目文件中进行以下更改:

  1. 设置 PropertyGroup 的值。将 TargetFramework 指定为 net8.0

  2. 设置 PropertyGroup 的值。将 AzureFunctionsVersion 指定为 v4

  3. 将以下 OutputType 元素添加到 PropertyGroup

    <OutputType>Exe</OutputType>
    
  4. ItemGroup.PackageReference 列表中,把对 Microsoft.NET.Sdk.Functions 的包引用替换为以下引用:

      <FrameworkReference Include="Microsoft.AspNetCore.App" />
      <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.21.0" />
      <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.17.2" />
      <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="1.2.1" />
      <PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" />
      <PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.2.0" />
    

    记下对 Microsoft.Azure.WebJobs.* 命名空间中其他包的所有引用。 你将后面的步骤中替换这些包。

  5. 添加以下新的 ItemGroup

    <ItemGroup>
      <Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext"/>
    </ItemGroup>
    

进行这些更改后,更新的项目应如以下示例所示:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
    <RootNamespace>My.Namespace</RootNamespace>
    <OutputType>Exe</OutputType>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.21.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.17.2" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="1.2.1" />
    <PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.2.0" />
    <!-- Other packages may also be in this list -->
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
  <ItemGroup>
    <Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext"/>
  </ItemGroup>
</Project>

包引用

迁移到独立辅助角色模型时,需要更改应用程序引用的包。

如果尚未更新,请更新项目以引用以下项的最新稳定版本:

根据应用使用的触发器和绑定,你的应用可能需要引用一组不同的包。 下表显示了一些最常用的扩展的替代项:

方案 对包引用的更改
计时器触发器 添加
Microsoft.Azure.Functions.Worker.Extensions.Timer
存储绑定 Replace
Microsoft.Azure.WebJobs.Extensions.Storage
替换为
Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs
Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues
Microsoft.Azure.Functions.Worker.Extensions.Tables
Blob 绑定 把对
Microsoft.Azure.WebJobs.Extensions.Storage.Blobs
的引用替换为最新版本的
Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs
队列绑定 把对
Microsoft.Azure.WebJobs.Extensions.Storage.Queues
的引用替换为最新版本的
Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues
表绑定 把对
Microsoft.Azure.WebJobs.Extensions.Tables
的引用替换为最新版本的
Microsoft.Azure.Functions.Worker.Extensions.Tables
Cosmos DB 绑定 把对
Microsoft.Azure.WebJobs.Extensions.CosmosDB
和/或
Microsoft.Azure.WebJobs.Extensions.DocumentDB
的引用替换为最新版本的
Microsoft.Azure.Functions.Worker.Extensions.CosmosDB
服务总线绑定 把对
Microsoft.Azure.WebJobs.Extensions.ServiceBus
的引用替换为最新版本的
Microsoft.Azure.Functions.Worker.Extensions.ServiceBus
事件中心绑定 把对
Microsoft.Azure.WebJobs.Extensions.EventHubs
的引用替换为最新版本的
Microsoft.Azure.Functions.Worker.Extensions.EventHubs
事件网格绑定 把对
Microsoft.Azure.WebJobs.Extensions.EventGrid
的引用替换为最新版本的
Microsoft.Azure.Functions.Worker.Extensions.EventGrid
SignalR 服务绑定 把对
Microsoft.Azure.WebJobs.Extensions.SignalRService
的引用替换为最新版本的
Microsoft.Azure.Functions.Worker.Extensions.SignalRService
Durable Functions 把对
Microsoft.Azure.WebJobs.Extensions.DurableTask
的引用替换为最新版本的
Microsoft.Azure.Functions.Worker.Extensions.DurableTask
Durable Functions
(SQL 存储提供程序)
把对
Microsoft.DurableTask.SqlServer.AzureFunctions
的引用替换为最新版本的
Microsoft.Azure.Functions.Worker.Extensions.DurableTask.SqlServer
Durable Functions
(Netherite 存储提供程序)
把对
Microsoft.Azure.DurableTask.Netherite.AzureFunctions
的引用替换为最新版本的
Microsoft.Azure.Functions.Worker.Extensions.DurableTask.Netherite
SendGrid 绑定 把对
Microsoft.Azure.WebJobs.Extensions.SendGrid
的引用替换为最新版本的
Microsoft.Azure.Functions.Worker.Extensions.SendGrid
Kafka 绑定 把对
Microsoft.Azure.WebJobs.Extensions.Kafka
的引用替换为最新版本的
Microsoft.Azure.Functions.Worker.Extensions.Kafka
RabbitMQ 绑定 把对
Microsoft.Azure.WebJobs.Extensions.RabbitMQ
的引用替换为最新版本的
Microsoft.Azure.Functions.Worker.Extensions.RabbitMQ
依赖关系注入
和启动配置
移除了对以下项的引用
Microsoft.Azure.Functions.Extensions
(独立工作器模型默认提供此功能。)

有关要考虑的扩展的完整列表,请参阅受支持的绑定;有关独立进程模型的完整安装说明,请参阅每个扩展的文档。 必须安装任何目标包的最新稳定版本。

提示

在此过程中对扩展版本所做的任何更改可能还要求你更新 host.json 文件。 请务必阅读所使用的每个扩展的文档。 例如,服务总线扩展在版本 4.x 和 5.x 之间的结构中发生了中断性变更。 有关详细信息,请参阅 Azure Functions 的 Azure 服务总线绑定

隔离的工作器模型应用程序不能引用 Microsoft.Azure.WebJobs.* 命名空间中的任何包,也不能引用 Microsoft.Azure.Functions.Extensions 如果有对这些内容的任何剩余引用,应将其删除。

提示

应用还可能依赖于 Azure SDK 类型,无论是作为触发器和绑定的一部分,还是作为独立的依赖项。 还应利用此机会更新这些内容。 最新版本的 Functions 扩展适用于最新版本的Azure SDK for .NET,这些内容几乎所有的包都是Azure.*形式。

Program.cs 文件

当迁移以在独立的工作进程中运行时,必须将包含以下内容的 Program.cs 文件添加到项目中:

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication()
    .ConfigureServices(services => {
        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
    })
    .Build();

host.Run();

此示例包括 ASP.NET Core 集成以提高性能,并在应用使用 HTTP 触发器时提供熟悉的编程模型。 如果不打算使用 HTTP 触发器,则可以将对 ConfigureFunctionsWebApplication 的调用替换为对 ConfigureFunctionsWorkerDefaults 的调用。 如果这样做,则可以从项目文件中删除对 Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore 的引用。 但是,为了获得最佳性能,即使对于具有其他触发器类型的函数,也应保留对 ASP.NET Core 的 FrameworkReference

Program.cs 文件将替换任何具有 FunctionsStartup 属性的文件(通常是 Startup.cs 文件)。 在 FunctionsStartup 代码将引用 IFunctionsHostBuilder.Services 的位置,可以改为在 Program.csHostBuilder.ConfigureServices() 方法中添加语句。 若要了解有关使用 Program.cs 的详细信息,请参阅独立工作器模型指南中的启动和配置

上面默认的 Program.cs 示例包括独立辅助角色模型的 Application Insights 集成设置。 在你的 Program.cs 中,还必须配置任何应该应用于项目中代码的日志的日志筛选。 在隔离的辅助角色模型中,host.json 文件仅控制 Functions 主机运行时发出的事件。 如果未在 Program.cs 中配置筛选规则,则可能会看到遥测中存在各种类别的日志级别差异。

尽管可以将自定义配置源注册为 HostBuilder 中的一部分,但请注意,这些源同样仅适用于你的项目中的代码。 平台还需要触发器和绑定配置,这应通过应用程序设置Key Vault 引用应用程序配置引用功能提供。

将任何现有 FunctionsStartup 中的所有内容移动到 Program.cs 文件后,便可以删除 FunctionsStartup 属性及其应用到的类。

函数签名更改

某些关键类型在进程内模型和独立辅助角色模型之间发生更改。 其中许多都与构成函数签名的属性、参数和返回类型相关。 对于每个函数,必须对以下各项进行更改:

  • 函数属性(也会设置函数的名称)
  • 函数如何获取 ILogger/ILogger<T>
  • 触发器和绑定属性和参数

本节的剩余部分将引导你完成每个步骤。

函数特性

在独立工作器模型中,Function 属性取代了 FunctionName 属性。 新属性的签名相同,唯一的区别在于名称。 因此,你可以在整个项目中执行字符串替换。

日志记录

在进程内模型中,可以在函数中包含其他 ILogger 参数,也可以使用依赖项注入来获取一个 ILogger<T>。 如果已在使用依赖项注入,则相同的机制在独立工作器模型中运行。

但对于依赖于 ILogger 方法参数的任何函数,则需要进行更改。 建议使用依赖项注入来获取一个 ILogger<T>。 使用以下步骤迁移函数的日志记录机制:

  1. 在函数类中,添加一个 private readonly ILogger<MyFunction> _logger; 属性,并将 MyFunction 替换为函数类的名称。

  2. 为函数类创建一个构造函数,该函数类采用 ILogger<T> 作为参数:

    public MyFunction(ILogger<MyFunction> logger) {
        _logger = logger;
    }
    

    将上述代码片段中的这两个 MyFunction 实例替换为函数类的名称。

  3. 对于函数代码中的日志记录操作,请将对参数的 ILogger 引用替换为对 _logger 的引用。

  4. 从函数签名中移除 ILogger 参数。

若要了解详细信息,请参阅独立工作器模型中的日志记录

触发器和绑定更改

在上一步中更改包引用时,你在触发器和绑定中引入了错误,现在要修复这些错误:

  1. 删除任何 using Microsoft.Azure.WebJobs; 语句。

  2. 添加一个 using Microsoft.Azure.Functions.Worker; 语句。

  3. 对于每个绑定属性,按照其参考文档中指定的方式更改属性的名称,可以在支持的绑定索引中找到该文档。 一般情况下,属性名称会更改,如下所示:

    • 触发器通常以相同的方式保持命名。 例如,这两个模型的属性名称都是 QueueTrigger
    • 输入绑定通常需要将“Input”添加到其名称中。 例如,如果在进程内模型中使用了 CosmosDB 输入绑定属性,则现在为 CosmosDBInput
    • 输出绑定通常需要将“Output”添加到其名称中。 例如,如果在进程内模型中使用了 Queue 输出绑定属性,则现在为 QueueOutput
  4. 更新属性参数以反映独立工作器模型版本,如绑定的参考文档中指定。

    例如,在进程内模型中,Blob 输出绑定由包含 Access 属性的 [Blob(...)] 属性来表示。 在独立工作器模型中,Blob 输出属性将为 [BlobOutput(...)]。 绑定不再需要该 Access 属性,因此可以删除该参数。 因此 [Blob("sample-images-sm/{fileName}", FileAccess.Write, Connection = "MyStorageConnection")] 将变为 [BlobOutput("sample-images-sm/{fileName}", Connection = "MyStorageConnection")]

  5. 将输出绑定移出函数参数列表。 如果只有一个输出绑定,则可以将此应用到函数的返回类型。 如果有多个输出,请为每个输出创建一个具有特性的新类,并将属性应用于这些特性。 若要了解详细信息,请参阅多个输出绑定

  6. 查阅每个绑定的参考文档,以了解允许绑定到的类型。 在某些情况下,可能需要更改类型。 对于输出绑定,如果进程内模型版本使用了一个 IAsyncCollector<T>,则可以将其替换为目标类型的数组的绑定:T[]。 还可以考虑将输出绑定替换为它所表示的服务的客户端对象,或者作为输入绑定的绑定类型(如果可用),或者自己注入客户端

  7. 如果函数包含 IBinder 参数,请将其移除。 将该功能替换为它所表示的服务的客户端对象,或者作为输入绑定的绑定类型(如果可用),或者自己注入客户端

  8. 更新函数代码以使用任何新类型。

local.settings.json 文件

只有在本地运行时才使用 local.settings.json 文件。 有关信息,请参阅本地设置文件

从进程内运行迁移到在独立工作进程中运行时,需要将FUNCTIONS_WORKER_RUNTIME值更改为 "dotnet-isolated"。 确保 local.settings.json 文件至少包含以下元素:

{
    "IsEncrypted": false,
    "Values": {
        "AzureWebJobsStorage": "UseDevelopmentStorage=true",
        "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
    }
}

为“AzureWebJobsStorage”配置的值可能有所不同。 无需在迁移过程中更改其值。

host.json 文件

无需对 host.json 文件进行更改。 但是,如果此文件中的 Application Insights 配置来自你的进程内模型项目,则可能需要在 Program.cs 文件中进行其他更改。 host.json 文件仅控制来自 Functions 主机运行时的日志记录,在隔离的辅助角色模型中,其中一些日志直接来自应用程序,这给了你更多控制。 有关如何筛选这些日志的详细信息,请参阅在独立辅助角色模型中管理日志级别

其他代码更改

本部分重点介绍在迁移过程中要考虑的其他代码更改。 不是所有应用程序都需要这些更改,但你应评估它们是否与你的方案相关。

JSON 序列化

默认情况下,独立辅助角色模型将 System.Text.Json 用于 JSON 序列化。 若要自定义序列化程序选项或切换到 JSON.NET (Newtonsoft.Json),请参阅这些说明

Application Insights 日志级别和筛选

日志可以从 Functions 主机运行时和你项目中的代码发送到 Application Insights。 host.json 让你可以为主机日志记录配置规则,但要控制来自你的代码的日志,需要将筛选规则配置为你的 Program.cs 的一部分。 有关如何筛选这些日志的详细信息,请参阅在独立辅助角色模型中管理日志级别

函数迁移示例

HTTP 触发器示例

进程内模型的 HTTP 触发器可能如以下示例所示:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;

namespace Company.Function
{
    public static class HttpTriggerCSharp
    {
        [FunctionName("HttpTriggerCSharp")]
        public static IActionResult Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            return new OkObjectResult($"Welcome to Azure Functions, {req.Query["name"]}!");
        }
    }
}

迁移版本的 HTTP 触发器可能如以下示例所示:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;

namespace Company.Function
{
    public class HttpTriggerCSharp
    {
        private readonly ILogger<HttpTriggerCSharp> _logger;

        public HttpTriggerCSharp(ILogger<HttpTriggerCSharp> logger)
        {
            _logger = logger;
        }

        [Function("HttpTriggerCSharp")]
        public IActionResult Run(
            [HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequest req)
        {
            _logger.LogInformation("C# HTTP trigger function processed a request.");

            return new OkObjectResult($"Welcome to Azure Functions, {req.Query["name"]}!");
        }
    }
}

更新 Azure 中的函数应用

将函数应用升级到独立模型包括两个步骤:

  1. 通过将 FUNCTIONS_WORKER_RUNTIME 应用程序设置设置为 dotnet-isolated,将函数应用的配置更改为使用独立模型。 确保任何部署自动化都进行了类似的更新。
  2. 将迁移的项目发布到更新的函数应用。

使用 Visual Studio 将独立的工作器模型项目发布到使用进程内模型的现有函数应用时,系统会提示你让 Visual Studio 在部署期间更新函数应用。 这会同时完成这两个步骤。

如果需要最大程度地减少停机时间,请考虑使用过渡槽通过 Azure 中的更新后配置测试和验证迁移后的代码。 然后,可以通过交换操作将完全迁移的应用部署到生产槽。

完成这些步骤后,应用已完全迁移到独立模型。 恭喜! 对于需要迁移的任何其他应用,请根据需要重复本指南中的步骤。

后续步骤