共用方式為

Azure Functions 与 Aspire (预览版)

Aspire 是一个有意见的堆栈,可简化云中分布式应用程序的开发。 Aspire 与 Azure Functions 的集成使你能够开发、调试和协调 Azure Functions .NET 项目,作为 Aspire 应用主机的一部分。

重要

Aspire 与 Azure Functions 的集成目前为预览版,可能会更改。

先决条件

设置用于将 Azure Functions 与 Aspire 配合使用的开发环境:

  • 安装 .NET 9 SDKAspire 9.0 或更高版本。 尽管需要 .NET 9 SDK,但 Aspire 9.0 支持 .NET 8 和 .NET 9 框架。
  • 如果你使用的是 Visual Studio,请将其更新到 17.12 版本或更高版本。 还必须具有最新版本的适用于 Visual Studio 的 Azure Functions 工具。 检查更新:
    1. 转到 “工具>选项”。
    2. “项目和解决方案”下,选择 “Azure Functions”。
    3. 选择“检查更新”并按提示安装更新。

注释

Azure Functions 与 Aspire 的集成尚不支持 .NET 10 预览版。

解决方案结构

使用 Azure Functions 和 Aspire 的解决方案具有多个项目,包括 应用主机项目 和一个或多个 Functions 项目。

应用主机项目是应用程序的入口点。 它协调应用程序的组件(包括 Functions 项目)的设置。

解决方案通常还包括 服务默认 项目。 此项目提供一组默认服务和配置,用于应用程序中的项目。

应用托管项目

若要成功配置集成,请确保应用主机项目满足以下要求:

  • 应用主机项目必须引用 Aspire.Hosting.Azure.Functions。 此包定义集成所需的逻辑。
  • 对于你希望包含在业务流程中的每个 Functions 项目,应用主机项目都需要有一个项目引用。
  • 在应用主机的 AppHost.cs 文件中,必须通过调用 AddAzureFunctionsProject<TProject>() 实例上的 IDistributedApplicationBuilder 来包含项目。 使用此方法,而不是使用 AddProject<TProject>() 在 Aspire 中用于其他项目类型的方法。 如果使用 AddProject<TProject>(),Functions 项目无法正确启动。

以下示例演示应用主机项目的最小 AppHost.cs 文件:

var builder = DistributedApplication.CreateBuilder(args);

builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject");

builder.Build().Run();

Azure Functions 项目

若要成功配置集成,请确保 Azure Functions 项目满足以下要求:

以下示例演示 Aspire 中使用的 Functions 项目的最小 Program.cs 文件:

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

var builder = FunctionsApplication.CreateBuilder(args);

builder.AddServiceDefaults();

builder.ConfigureFunctionsWebApplication();

builder.Build().Run();

此示例不包括出现在许多其他 Program.cs 示例和 Azure Functions 模板中的默认 Application Insights 配置。 相反,通过在 Aspire 中调用builder.AddServiceDefaults方法来配置 OpenTelemetry 集成。

若要充分利用集成,请考虑以下准则:

  • 不要在 Functions 项目中包括任何直接的 Application Insights 集成。 Aspire 中的监视相反由 OpenTelemetry 支持来实现。 可以将 Aspire 配置为通过服务默认项目将数据导出到 Azure Monitor。
  • 不要在 local.settings.json Functions 项目的文件中定义自定义应用设置。 应位于 local.settings.json 中的唯一设置是 "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"。 通过应用主机项目设置所有其他应用配置。

使用 Aspire 的连接配置

应用主机项目定义资源,并帮助你使用代码在它们之间创建连接。 本部分介绍如何配置和自定义 Azure Functions 项目使用的连接。

Aspire 包括有助于入门的默认连接权限。 但是,这些权限可能不适合或足以满足应用程序要求。

对于使用 Azure 基于角色的访问控制(RBAC)的方案,可以通过对项目资源调用 WithRoleAssignments() 方法来自定义权限。 调用 WithRoleAssignments()时,将删除所有默认角色分配,并且必须显式定义所需的完整角色分配。 如果您的应用程序托管在 Azure 容器应用中,使用WithRoleAssignments()时还需要在AddAzureContainerAppEnvironment()上调用DistributedApplicationBuilder

Azure Functions 主机存储

Azure Functions 需要主机存储连接 (AzureWebJobsStorage) 才能实现其多个核心行为。 在应用主机项目中调用 AddAzureFunctionsProject<TProject>() 时,默认情况下会创建一个 AzureWebJobsStorage 连接,并提供给 Functions 项目。 此默认连接使用 Azure 存储模拟器进行本地开发运行,并在部署存储帐户时自动预配存储帐户。 若要获得更多控制,可以通过调用 .WithHostStorage() Functions 项目资源来替换此连接。

Aspire 为主机存储连接设置的默认权限取决于你是否调用 WithHostStorage() 。 添加 WithHostStorage() 会删除存储帐户参与者分配。 下表列出了 Aspire 为主机存储连接设置的默认权限:

主机存储连接 默认角色
不调用 WithHostStorage() 存储 Blob 数据参与者
存储队列数据参与者
存储表数据参与者
存储帐户贡献者
调用 WithHostStorage() 存储 Blob 数据参与者
存储队列数据参与者
存储表数据参与者

以下示例显示了用于替换主机存储并指定角色分配的应用主机项目的最小 AppHost.cs 文件:

using Azure.Provisioning.Storage;

var builder = DistributedApplication.CreateBuilder(args);

builder.AddAzureContainerAppEnvironment("myEnv");

var myHostStorage = builder.AddAzureStorage("myHostStorage");

builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
    .WithHostStorage(myHostStorage)
    .WithRoleAssignments(myHostStorage, StorageBuiltInRole.StorageBlobDataOwner);

builder.Build().Run();

注释

存储 Blob 数据所有者”是我们针对主机存储连接的基本需求推荐的角色。 如果与 Blob 服务的连接只有 存储 Blob 数据参与者的 Aspire 默认值,则应用可能会遇到问题。

对于生产场景,请包括对 WithHostStorage()WithRoleAssignments() 的调用。 然后,可以显式设置此角色,同时设置所需的任何其他角色。

触发器和绑定连接

触发器和绑定按名称引用连接。 以下 Aspire 集成通过调用项目资源中的 WithReference() 来提供这些连接:

Aspire 集成 默认角色
Azure Blob 存储服务 存储 Blob 数据参与者
存储队列数据参与者
存储表数据参与者
Azure 队列存储 存储 Blob 数据参与者
存储队列数据参与者
存储表数据参与者
Azure 事件中心 Azure 事件中心数据所有者
Azure 服务总线 Azure 服务总线数据所有者

以下示例展示了一个用于应用主机项目的最小 AppHost.cs 文件,该项目配置了一个队列触发器。 在此示例中,相应的队列触发器的 Connection 属性设置为 MyQueueTriggerConnection,因此调用时指定了 WithReference() 的名称。

var builder = DistributedApplication.CreateBuilder(args);

var myAppStorage = builder.AddAzureStorage("myAppStorage").RunAsEmulator();
var queues = myAppStorage.AddQueues("queues");

builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
    .WithReference(queues, "MyQueueTriggerConnection");

builder.Build().Run();

对于其他集成,调用 WithReference 以不同的方式设置配置。 它们使配置可用于 Aspire 客户端集成,但不能用于触发器和绑定。 对于这些集成,调用 WithEnvironment() 传递触发器或绑定的连接信息以进行解析。

以下示例演示如何为公开连接字符串表达式的资源设置环境变量 MyBindingConnection

builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
    .WithEnvironment("MyBindingConnection", otherIntegration.Resource.ConnectionStringExpression);

如果希望 Aspire 客户端集成和触发器和绑定系统都使用连接,则可以同时配置 WithReference()WithEnvironment()

对于某些资源,在本地运行和发布到 Azure 时的连接结构可能会有所不同。 在之前的示例中,otherIntegration 可以是作为模拟器运行的资源,因此 ConnectionStringExpression 将返回模拟器连接字符串。 但是,发布资源时,Aspire 可能会设置基于标识的连接,并 ConnectionStringExpression 返回服务的 URI。 在这种情况下,若要 为 Azure Functions 设置基于标识的连接,可能需要提供不同的环境变量名称。

以下示例使用 builder.ExecutionContext.IsPublishMode 以有条件地添加必要的后缀:

builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
    .WithEnvironment("MyBindingConnection" + (builder.ExecutionContext.IsPublishMode ? "__serviceUri" : ""), otherIntegration.Resource.ConnectionStringExpression);

有关每个绑定支持的连接格式以及这些格式所需的权限的详细信息,请参阅绑定的 参考页

注意事项和最佳做法

在评估 Azure Functions 与 Aspire 的集成时,请考虑以下几点:

  • 对集成的支持目前为预览版。

  • 使用 Aspire 的触发器和绑定配置目前仅限于特定的集成方案。 有关详细信息,请参阅本文中的 Aspire 连接配置

  • 函数项目的Program.cs文件应使用主机实例启动IHostApplicationBuilder版本。 IHostApplicationBuilder 允许调用 builder.AddServiceDefaults()Aspire 服务默认值 添加到 Functions 项目。

  • Aspire 使用 OpenTelemetry 进行监视。 可以将 Aspire 配置为通过服务默认项目将数据导出到 Azure Monitor。

    在许多其他 Azure Functions 上下文中,你可以通过注册辅助角色服务来包含与 Application Insights 的直接集成。 我们不建议在 Aspire 中实现这种集成。 这可能会导致Microsoft.ApplicationInsights.WorkerService 在版本 2.22.0 下发生运行时错误,但版本 2.23.0 解决了此问题。 使用 Aspire 时,请从 Functions 项目中删除任何直接的 Application Insights 集成。

  • 对于登记到 Aspire 业务流程中的 Functions 项目,大部分应用程序配置应来自 Aspire 应用主机项目。 避免在 local.settings.json 中设置除 FUNCTIONS_WORKER_RUNTIME 设置之外的任何内容。 如果您在 local.settings.json 和 Aspire 中设置相同的环境变量,系统将使用 Aspire 的版本。

  • 不要为任何 local.settings.json连接配置 Azure 存储模拟器。 许多 Functions 起始模板将模拟器作为 AzureWebJobsStorage 的默认选项。 但是,模拟器配置可能会提示某些开发人员工具启动与 Aspire 使用的版本冲突的模拟器版本。