你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
.NET Aspire 是一个有观点的堆栈,可简化云中分布式应用程序的开发。 通过 .NET Aspire 与 Azure Functions 的集成,可以将 Azure Functions .NET 项目作为 .NET Aspire 应用主机的一部分进行开发、调试和协调。
重要
.NET Aspire 与 Azure Functions 的集成目前以预览版提供,可能会更改。
先决条件
设置用于将 Azure Functions 与 .NET Aspire 配合使用的开发环境:
- 安装 .NET 9 SDK 和 .NET Aspire 9.0 或更高版本。 尽管需要 .NET 9 SDK,但 .NET Aspire 9.0 支持 .NET 8 和 .NET 9 框架。
- 如果你使用的是 Visual Studio,请将其更新到 17.12 版本或更高版本。 还必须具有最新版本的适用于 Visual Studio 的 Azure Functions 工具。 检查更新:
- 转到“工具”“选项” 。
- 在 “项目和解决方案”下,选择 “Azure Functions”。
- 选择“检查更新”并按提示安装更新。
解决方案结构
使用 Azure Functions 和 .NET Aspire 的解决方案具有多个项目,包括 应用主机项目 和一个或多个 Functions 项目。
应用主机项目是应用程序的入口点。 它协调应用程序的组件(包括 Functions 项目)的设置。
解决方案通常还包括 服务默认 项目。 此项目提供一组默认服务和配置,用于应用程序中的项目。
应用托管项目
若要成功配置集成,请确保应用主机项目满足以下要求:
- 应用主机项目必须引用 Aspire.Hosting.Azure.Functions。 此包定义集成所需的逻辑。
- 对于你希望包含在业务流程中的每个 Functions 项目,应用主机项目都需要有一个项目引用。
- 在应用主机的
Program.cs
文件中,必须通过调用IDistributedApplicationBuilder
实例上的AddAzureFunctionsProject<TProject>()
来包含项目。 使用此方法,而不是使用AddProject<TProject>()
方法,正如您在 .NET Aspire 中为其他项目类型所做的那样。 如果使用AddProject<TProject>()
,Functions 项目无法正确启动。
以下示例演示应用主机项目的最小 Program.cs
文件:
var builder = DistributedApplication.CreateBuilder(args);
builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject");
builder.Build().Run();
Azure Functions 项目
若要成功配置集成,请确保 Azure Functions 项目满足以下要求:
Functions 项目必须引用 Microsoft.Azure.Functions.Worker 和 Microsoft.Azure.Functions.Worker.Sdk 的 2.x 版本。 还必须更新对 2.x 版本的任何 Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore 引用。
您的
Program.cs
文件必须使用主机实例启动的IHostApplicationBuilder
版本。 此要求意味着必须使用FunctionsApplication.CreateBuilder(args)
。如果解决方案包含服务默认项目,请确保 Functions 项目配置为使用它:
- Functions 项目应包含对服务默认设置项目的项目引用。
- 在
Program.cs
中生成IHostApplicationBuilder
之前,请包括对builder.AddServiceDefaults()
的调用。
以下示例演示 .NET 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 配置。 而是通过调用该方法 builder.AddServiceDefaults
在 .NET Aspire 中配置 OpenTelemetry 集成。
若要充分利用集成,请考虑以下准则:
- 不要在 Functions 项目中包括任何直接的 Application Insights 集成。 而 .NET Aspire 中的监视通过 OpenTelemetry 支持进行处理。 可以将 .NET Aspire 配置为通过服务默认项目将数据导出到 Azure Monitor。
- 不要在
local.settings.json
Functions 项目的文件中定义自定义应用设置。 应位于local.settings.json
中的唯一设置是"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
。 通过应用主机项目设置所有其他应用配置。
使用 .NET Aspire 的连接配置
应用主机项目定义资源,并帮助你使用代码在它们之间创建连接。 本部分介绍如何配置和自定义 Azure Functions 项目使用的连接。
.NET Aspire 包括有助于入门的默认连接权限。 但是,这些权限可能不适合或足以满足应用程序要求。
对于使用 Azure 基于角色的访问控制(RBAC)的方案,可以通过对项目资源调用 WithRoleAssignments()
方法来自定义权限。 调用 WithRoleAssignments()
时,将删除所有默认角色分配,并且必须显式定义所需的完整角色分配。 如果您的应用程序托管在 Azure 容器应用中,使用WithRoleAssignments()
时还需要在DistributedApplicationBuilder
上调用AddAzureContainerAppEnvironment()
。
Azure Functions 主机存储
Azure Functions 需要主机存储连接 (AzureWebJobsStorage
) 才能实现其多个核心行为。 在应用主机项目中调用 AddAzureFunctionsProject<TProject>()
时,默认情况下会创建一个 AzureWebJobsStorage
连接,并提供给 Functions 项目。 此默认连接使用 Azure 存储模拟器进行本地开发运行,并在部署存储帐户时自动预配存储帐户。 若要获得更多控制,可以通过调用 .WithHostStorage()
Functions 项目资源来替换此连接。
.NET Aspire 为主机存储连接设置的默认权限取决于你是否调用 WithHostStorage()
。 添加 WithHostStorage()
会删除存储帐户参与者分配。 下表列出了 .NET Aspire 为主机存储连接设置的默认权限:
主机存储连接 | 默认角色 |
---|---|
不调用 WithHostStorage() |
存储 Blob 数据参与者、 存储队列数据参与者、 存储表数据参与者: 存储帐户贡献者 |
调用 WithHostStorage() |
存储 Blob 数据参与者、 存储队列数据参与者、 存储表数据参与者 |
以下示例显示了用于替换主机存储并指定角色分配的应用主机项目的最小 Program.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 数据参与者”的 .NET Aspire 默认设置,则应用可能会遇到问题。
对于生产场景,请包括对 WithHostStorage()
和 WithRoleAssignments()
的调用。 然后,可以显式设置此角色,同时设置所需的任何其他角色。
触发器和绑定连接
触发器和绑定按名称引用连接。 以下 .NET Aspire 集成通过调用项目资源中的 WithReference()
提供这些连接:
.NET Aspire 集成 | 默认角色 |
---|---|
Azure Blob 存储服务 | 存储 Blob 数据参与者、 存储队列数据参与者、 存储表数据参与者 |
Azure 队列存储 | 存储 Blob 数据参与者、 存储队列数据参与者、 存储表数据参与者 |
Azure 事件中心 | Azure 事件中心数据所有者 |
Azure 服务总线 | Azure 服务总线数据所有者 |
以下示例展示了一个用于应用主机项目的最小 Program.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
以不同的方式设置配置。 这些配置可用于.NET Aspire 客户端集成,但不可用于触发和绑定。 对于这些集成,调用 WithEnvironment()
传递触发器或绑定的连接信息以进行解析。
以下示例演示如何为公开连接字符串表达式的资源设置环境变量 MyBindingConnection
:
builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
.WithEnvironment("MyBindingConnection", otherIntegration.Resource.ConnectionStringExpression);
如果希望 .NET Aspire 客户端集成和触发器和绑定系统都使用连接,则可以同时配置 WithReference()
和 WithEnvironment()
。
对于某些资源,在本地运行和发布到 Azure 时的连接结构可能会有所不同。 在之前的示例中,otherIntegration
可以是作为模拟器运行的资源,因此 ConnectionStringExpression
将返回模拟器连接字符串。 但是,发布资源时,.NET Aspire 可能会设置基于标识的连接,并 ConnectionStringExpression
返回服务的 URI。 在这种情况下,若要 为 Azure Functions 设置基于标识的连接,可能需要提供不同的环境变量名称。
以下示例使用 builder.ExecutionContext.IsPublishMode
以有条件地添加必要的后缀:
builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
.WithEnvironment("MyBindingConnection" + (builder.ExecutionContext.IsPublishMode ? "__serviceUri" : ""), otherIntegration.Resource.ConnectionStringExpression);
有关每个绑定支持的连接格式以及这些格式所需的权限的详细信息,请参阅绑定的 参考页。
托管应用程序
默认情况下,将 Azure Functions 项目发布到 Azure 时,它将部署到 Azure 容器应用。
在预览期间,容器应用资源不支持事件驱动的缩放。 Azure Functions 支持不适用于在此模式下部署的应用。 如果需要开具支持票证,请选择 Azure 容器应用资源类型。
注意事项和最佳做法
评估 Azure Functions 与 .NET Aspire 的集成时,请考虑以下几点:
对集成的支持目前为预览版。
通过 .NET Aspire 的触发器和绑定配置目前仅限于特定的集成。 有关详细信息,请参阅本文中的 .NET Aspire 连接配置 。
Program.cs
文件应使用IHostApplicationBuilder
版本的主机实例启动。IHostApplicationBuilder
允许调用builder.AddServiceDefaults()
以将 .NET Aspire 服务默认值 添加到 Functions 项目。.NET Aspire 使用 OpenTelemetry 进行监视。 可以将 .NET Aspire 配置为通过服务默认项目将数据导出到 Azure Monitor。
在许多其他 Azure Functions 上下文中,你可以通过注册辅助角色服务来包含与 Application Insights 的直接集成。 不建议在 .NET Aspire 中集成此类。 这可能会导致
Microsoft.ApplicationInsights.WorkerService
在版本 2.22.0 下发生运行时错误,但版本 2.23.0 解决了此问题。 使用 .NET Aspire 时,请从 Functions 项目中删除任何直接 Application Insights 集成。对于登记到 .NET Aspire 业务流程中的 Functions 项目,大多数应用程序配置应来自 .NET Aspire 应用主机项目。 避免在
local.settings.json
中设置除FUNCTIONS_WORKER_RUNTIME
设置之外的任何内容。 如果在 .NET Aspire 中local.settings.json
设置相同的环境变量,则系统会使用 .NET Aspire 版本。不要为任何
local.settings.json
连接配置 Azure 存储模拟器。 许多 Functions 起始模板将模拟器作为AzureWebJobsStorage
的默认选项。 然而,模拟器的配置可能会导致某些开发工具启动一个与 .NET Aspire 使用的版本相冲突的模拟器版本。