你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
Azure Functions 开发人员指南
在 Azure Functions 中,所有函数都共享一些核心技术概念和组件,无论首选的语言或开发环境如何。 本文特定于语言。 在文章顶部选择首选的语言。
本文假定你已阅读 Azure Functions 概述。
如果你想立即开始,可以使用 Visual Studio、Visual Studio Code 或从命令提示符完成快速入门教程。
如果你想立即开始,可以使用 Maven(命令行)、Eclipse、IntelliJ IDEA、Gradle、Quarkus、Spring Cloud 或 Visual Studio Code。
如果希望直接开始,可以使用 Visual Studio Code 或从命令提示符完成快速入门教程。
如果希望直接开始,可以使用 Visual Studio Code 或从命令提示符完成快速入门教程。
如果希望直接开始,可以使用 Visual Studio Code 或从命令提示符完成快速入门教程。
如果希望直接开始,可以使用 Visual Studio Code 或从命令提示符完成快速入门教程。
代码项目
Azure Functions 的核心是特定于语言的代码项目,它实施一个或多个称为函数的代码执行单元。 函数只是根据事件、响应 HTTP 请求或按计划在 Azure 云中运行的方法。 将 Azure Functions 代码项目视为一种机制,用于组织、部署和集中管理项目中在 Azure 中运行的各个函数。 有关详细信息,请参阅组织函数。
设置代码项目布局的方式以及如何指示项目中哪些方法是函数取决于项目的开发语言。 有关特定于语言的详细指南,请参阅 C# 开发人员指南。
设置代码项目布局的方式以及如何指示项目中哪些方法是函数取决于项目的开发语言。 有关特定于语言的指南,请参阅 Java 开发人员指南。
设置代码项目布局的方式以及如何指示项目中哪些方法是函数取决于项目的开发语言。 有关特定于语言的指南,请参阅 Node.js 开发人员指南。
设置代码项目布局的方式以及如何指示项目中哪些方法是函数取决于项目的开发语言。 有关特定于语言的指南,请参阅 PowerShell 开发人员指南。
设置代码项目布局的方式以及如何指示项目中哪些方法是函数取决于项目的开发语言。 有关特定于语言的指南,请参阅 Python 开发人员指南。
所有函数都必须有一个触发器,它定义函数如何启动,并且可以为函数提供输入。 函数可以选择性地定义输入和输出绑定。 这些绑定简化了与其他服务的连接,你无需使用客户端 SDK。 有关详细信息,请参阅 Azure Functions 触发器和绑定概念。
Azure Functions 提供了一组特定于语言的项目和函数模板,可以轻松创建新的代码项目并向项目添加函数。 可以使用任何支持 Azure Functions 开发的工具,通过这些模板生成新的应用程序和函数。
开发工具
以下工具以您的首选语言提供 Azure Functions 的集成开发和发布体验:
这些工具与 Azure Functions Core Tools 集成,以便可以使用 Functions 运行时在本地计算机上运行和调试。 有关详细信息,请参阅在本地对 Azure Functions 进行编码和测试。
Azure 门户中还有一个编辑器,可用于直接在门户中更新代码和 function.json 定义文件。 应该仅使用此编辑器进行小的更改或创建概念验证功能。 应始终尽可能在本地开发函数。 有关详细信息,请参阅在 Azure 门户中创建首个函数。
仅 Node.js 版本 3 支持门户编辑,该版本使用 function.json 文件。
部署
将代码项目发布到 Azure 时,实质上是将项目部署到现有的函数应用资源。 函数应用在 Azure 中提供用于运行函数的执行上下文。 因此,它是函数的部署和管理单元。 从 Azure 资源的角度来看,函数应用相当于 Azure 应用服务中的站点资源 (Microsoft.Web/sites
),后者相当于 Web 应用。
函数应用由一个或多个共同管理、部署和缩放的独立函数组成。 函数应用中的所有函数共享相同的定价计划、部署方法和运行时版本。 有关详细信息,请参阅如何管理函数应用。
如果 Azure 中尚不存在函数应用和任何其他所需资源,首先需要创建这些资源,然后才能部署项目文件。 可以通过以下方式之一创建这些资源:
- Visual Studio 发布期间
以编程方式使用 Azure CLI、Azure PowerShell、ARM 模板或 Bicep 模板
在 Azure 门户中
除了基于工具的发布之外,Functions 还支持将源代码部署到现有函数应用的其他技术。 有关详细信息,请参阅 Azure Functions 中的部署技术。
连接到服务
任何基于云的计算服务的一个主要要求都是从其他云服务读取数据或将数据写入其他云服务。 Functions 提供了一组广泛的绑定,使你能够更轻松地连接到服务,而无需使用客户端 SDK。
无论是使用 Functions 提供的绑定扩展还是直接使用客户端 SDK,都可以安全地存储连接数据,并且不会将其包含在代码中。 有关详细信息,请参阅连接。
绑定
Functions 为许多 Azure 服务和一些作为扩展实施的第三方服务提供绑定。 有关详细信息,请参阅受支持绑定的完整列表。
绑定扩展可以支持输入和输出,并且许多触发器也充当输入绑定。 使用绑定可以配置与服务的连接,以便 Functions 主机可以处理数据访问。 有关详细信息,请参阅 Azure Functions 触发器和绑定概念。
如果您遇到来自绑定的错误问题,请参阅 Azure Functions 绑定错误代码文档。
客户端 SDK
虽然 Functions 提供绑定来简化函数代码中的数据访问,但如果你愿意,仍然可以在项目中使用客户端 SDK 直接访问给定的服务。 如果函数需要绑定扩展不支持的底层 SDK 功能,您可能需要直接使用客户端 SDK。
使用客户端 SDK 时,应该使用相同的过程来存储和访问绑定扩展所使用的连接字符串。
在函数中创建客户端 SDK 实例时,应该从环境变量中获取客户端所需的连接信息。
在函数中创建客户端 SDK 实例时,应该从环境变量中获取客户端所需的连接信息。
在函数中创建客户端 SDK 实例时,应该从环境变量中获取客户端所需的连接信息。
在函数中创建客户端 SDK 实例时,应该从环境变量中获取客户端所需的连接信息。
在函数中创建客户端 SDK 实例时,应该从环境变量中获取客户端所需的连接信息。
连接
作为安全最佳实践,Azure Functions 利用 Azure 应用服务的应用程序设置功能来帮助你更安全地存储连接到其他服务所需的字符串、密钥和其他令牌。 Azure 中的应用程序设置以加密方式存储,应用程序可以在运行时以环境变量 name
value
对的形式进行访问。 对于需要连接属性的触发器和绑定,可以设置应用程序设置名称而不是实际的连接字符串。 不能直接使用连接字符串或键配置绑定。
例如,请考虑具有 connection
属性的触发器定义。 可以将 connection
设置为包含连接字符串的环境变量的名称,而不是连接字符串。 使用此机密访问策略不仅可以使应用程序更加安全,而且还便于跨环境更改连接。 为了提高安全性,可以使用基于身份的连接。
默认配置提供程序使用环境变量。 在 Azure 中运行时,这些变量在“应用程序设置”中定义;在本地开发时,这些变量在“本地设置文件”中定义。
连接值
当连接名称解析为单个精确值时,运行时会将值标识为通常包含机密的连接字符串。 连接字符串的详细信息取决于连接的服务。
但是,连接名称也可以引用多个配置项目的集合,这可用于配置基于标识的连接。 可以通过使用以双下划线 __
结尾的共享前缀将环境变量视为集合。 然后,可以通过将连接名称设置为此前缀来引用该组。
例如,Azure Blob 触发器定义的 connection
属性可能是 Storage1
。 只要名为 Storage1
的环境变量没有配置单个字符串值,就可以使用名为 Storage1__blobServiceUri
的环境变量来通知连接的 blobServiceUri
属性。 每个服务的连接属性各不相同。 请参阅相关文档,了解使用连接的组件。
注意
使用 Azure 应用程序配置或 Key Vault 为托管标识连接提供设置时,设置名称应使用有效的键分隔符(例如 :
或 /
)替代 __
,以确保正确解析名称。
例如 Storage1:blobServiceUri
。
配置基于标识的连接
Azure Functions 中的某些连接配置为使用标识而不是机密。 支持取决于使用连接的扩展。 在某些情况下,即使连接到的服务支持基于标识的连接,Functions 中仍可能需要连接字符串。 有关使用托管标识配置函数应用的教程,请参阅使用基于标识的连接创建函数应用教程。
注意
如果在消耗计划或弹性高级计划中运行,在连接到函数应用使用的存储帐户上的 Azure 文件存储时,应用会使用 WEBSITE_AZUREFILESCONNECTIONSTRING
和 WEBSITE_CONTENTSHARE
设置。 Azure 文件存储在访问文件共享时不支持使用托管标识。 有关详细信息,请参阅 Azure 文件存储支持的身份验证方案
以下组件支持基于标识的连接:
连接源 | 支持的计划 | 了解更多 |
---|---|---|
Azure Blob 触发器和绑定 | All | Azure Blob 扩展版本 5.0.0 或更高版本, 扩展捆绑包 3.3.0 或更高版本 |
Azure 队列触发器和绑定 | All | Azure 队列扩展版本 5.0.0 或更高版本, 扩展捆绑包 3.3.0 或更高版本 |
Azure 表(使用 Azure 存储时) | All | Azure 表扩展版本 1.0.0 或更高版本, 扩展捆绑包 3.3.0 或更高版本 |
Azure SQL Database | 全部 | 使用托管标识和 SQL 绑定将函数应用连接到 Azure SQL |
Azure 事件中心触发器和绑定 | 全部 | Azure 事件中心扩展版本 5.0.0 或更高版本, 扩展捆绑包 3.3.0 或更高版本 |
Azure 服务总线触发器和绑定 | 全部 | Azure 服务总线扩展版本 5.0.0 或更高版本, 扩展捆绑包 3.3.0 或更高版本 |
Azure 事件网格输出绑定 | 全部 | Azure 事件网格扩展版本 3.3.0 或更高版本, 扩展捆绑包 3.3.0 或更高版本 |
Azure Cosmos DB 触发器和绑定 | 全部 | Azure Cosmos DB 扩展版本 4.0.0 或更高版本, 扩展捆绑包 4.0.2 或更高版本 |
Azure SignalR 触发器和绑定 | 全部 | Azure SignalR 扩展版本 1.7.0 或更高版本 扩展捆绑包 3.6.1 或更高版本 |
Durable Functions 存储提供程序(Azure 存储) | 全部 | Durable Functions 扩展 2.7.0 或更高版本, 扩展捆绑包 3.3.0 或更高版本 |
主机所需存储(“AzureWebJobsStorage”) | 全部 | 使用标识连接到主机存储 |
在 Azure Functions 服务中托管时,基于标识的连接将使用托管标识。 默认情况下使用系统分配的标识,但可以使用 credential
和 clientID
属性来指定用户分配的标识。 请注意,不支持为用户分配的标识配置资源 ID。 在其他上下文(如本地开发)中运行时,将改用开发人员标识,尽管可以进行自定义。 请参阅使用基于标识的连接进行本地开发。
向标识授予权限
无论使用何种标识,都必须具有执行所需操作的权限。 对于大多数 Azure 服务,这意味着你需要使用内置角色或者提供这些权限的自定义角色在 Azure RBAC 中分配角色。
重要
某些权限可能由并非所有上下文都需要的目标服务公开。 尽可能遵循最低权限原则,仅授予标识所需的权限。 例如,如果应用只需要从数据源进行读取即可,则使用仅具有读取权限的角色。 分配一个也具有该服务写入权限的角色并不恰当,因为对于读取操作来说,写入是多余的权限。 同样,你也希望确保角色分配的范围仅限于需要读取的资源。
选择以下选项卡之一以了解每个组件的权限:
- Azure Blob 扩展
- Azure 队列扩展
- Azure 表扩展
- 事件中心扩展
- 服务总线扩展
- 事件网格扩展
- Azure Cosmos DB 扩展
- Azure SignalR 扩展
- Durable Functions 存储提供程序
- Functions 主机存储
你需要创建一个角色分配,以在运行时提供对 Blob 容器的访问权限。 所有者等管理角色还不够。 下表显示了在正常操作中使用 Blob 存储扩展时建议使用的内置角色。 根据所编写的代码,应用程序可能需要进一步的权限。
绑定类型 | 内置角色示例 |
---|---|
触发器 | 存储 Blob 数据所有者和存储队列数据参与者1 此外,还必须向 AzureWebJobsStorage 连接授予额外的权限。2 |
输入绑定 | 存储 Blob 数据读者 |
输出绑定 | 存储 Blob 数据所有者 |
1 Blob 触发器通过将有害 blob 写入到连接所指定的存储帐户上的队列来处理多次重试中出现的故障。
2 AzureWebJobsStorage 连接在内部用于启用触发器的 blob 和队列。 如果将其配置为使用基于标识的连接,则该连接将需要超出默认要求的其他权限。 存储 Blob 数据所有者、存储队列数据参与者和存储帐户参与者角色涵盖了所需的权限。 若要了解详细信息,请参阅使用标识连接到主机存储。
基于标识的连接的通用属性
Azure 服务的基于标识的连接接受以下通用属性,其中 <CONNECTION_NAME_PREFIX>
是触发器或绑定定义中 connection
属性的值:
属性 | 环境变量模板 | 说明 |
---|---|---|
令牌凭据 | <CONNECTION_NAME_PREFIX>__credential |
定义如何为连接获取令牌。 如果部署的 Azure 函数打算使用托管标识身份验证,则此设置应设置为 managedidentity 。 仅当托管标识在托管环境中可用时,此值才有效。 |
客户端 ID | <CONNECTION_NAME_PREFIX>__clientId |
当 credential 设置为 managedidentity 时,此属性可以设为指定在获取令牌时要使用的用户分配的标识。 该属性接受与分配给应用程序的用户分配的标识对应的客户端 ID。 同时指定资源 ID 和客户端 ID 是无效的。 如果未指定,则使用系统分配的标识。 在本地开发方案中使用时,此属性的使用方式不同,且不应设置 credential 。 |
资源 ID | <CONNECTION_NAME_PREFIX>__managedIdentityResourceId |
当 credential 设置为 managedidentity 时,此属性可以设为指定在获取令牌时要使用的资源标识符。 该属性接受与用户定义的托管标识的资源 ID 对应的资源标识符。 同时指定资源 ID 和客户端 ID 是无效的。 如果两者都没有指定,则会使用系统分配的标识。 在本地开发方案中使用时,此属性的使用方式不同,且不应设置 credential 。 |
给定的连接类型可能支持其他选项。 请参阅相关文档,以了解用于建立连接的组件。
使用基于标识的连接进行本地开发
注意
使用基于身份的连接进行本地开发需要 Azure Functions Core Tools 4.0.3904
或更高版本。
在本地运行函数项目时,上述配置会告知运行时使用本地开发人员标识。 连接将尝试从以下位置获取令牌,顺序如下:
- Microsoft 应用程序之间共享的本地缓存
- Visual Studio 中的当前用户上下文
- Visual Studio Code 中的当前用户上下文
- Azure CLI 中的当前用户上下文
如果这些选项都不成功,则会出现错误。
你的标识可能已针对用于开发的 Azure 资源完成了一些角色分配,但这些角色可能不提供必需的数据访问权限。 所有者等管理角色还不够。 仔细检查每个组件的连接所需的权限,并确保已将它们分配给自己。
在某些情况下,你可能希望指定使用其他标识。 可以根据 Microsoft Entra 服务主体的客户端 ID 和客户端密码为指向备用标识的连接添加配置属性。 在 Azure Functions 服务中托管时,不支持此配置选项。 若要在本地计算机上使用 ID 和机密,请使用以下附加属性定义连接:
properties | 环境变量模板 | 说明 |
---|---|---|
租户 ID | <CONNECTION_NAME_PREFIX>__tenantId |
Microsoft Entra 租户(目录)ID。 |
客户端 ID | <CONNECTION_NAME_PREFIX>__clientId |
租户中应用注册的客户端(应用程序)ID。 |
客户端机密 | <CONNECTION_NAME_PREFIX>__clientSecret |
为应用注册生成的客户端密码。 |
以下是基于标识的 Azure Blob 连接所需的 local.settings.json
属性示例:
{
"IsEncrypted": false,
"Values": {
"<CONNECTION_NAME_PREFIX>__blobServiceUri": "<blobServiceUri>",
"<CONNECTION_NAME_PREFIX>__queueServiceUri": "<queueServiceUri>",
"<CONNECTION_NAME_PREFIX>__tenantId": "<tenantId>",
"<CONNECTION_NAME_PREFIX>__clientId": "<clientId>",
"<CONNECTION_NAME_PREFIX>__clientSecret": "<clientSecret>"
}
}
使用标识连接到主机存储
Azure Functions 主机使用 AzureWebJobsStorage
中设置的存储连接来启用核心行为(例如协调计时器触发器的单一实例执行)和默认应用密钥存储。 还可以将此连接配置为使用标识。
注意
Functions 中的其他组件依赖 AzureWebJobsStorage
来完成默认行为。 如果使用的是不支持此类连接的旧版本扩展(包括 Azure Blob、事件中心和 Durable Functions 的触发器和绑定),则不应将其移动到基于标识的连接。 同样,在 Linux 消耗计划中使用服务器端内部版本时,AzureWebJobsStorage
用于部署项目,并且,如果你启用此项,则将需要通过AzureWebJobsStorage
来进行部署。
此外,函数应用可能在其触发器、绑定和/或函数代码中将 AzureWebJobsStorage
重用于其他存储连接。 在从连接字符串更改此连接之前,请确保全部所用的 AzureWebJobsStorage
都能够使用基于标识的连接格式。
若要将基于标识的连接用于 AzureWebJobsStorage
,请配置以下应用设置:
设置 | 说明 | 示例值 |
---|---|---|
AzureWebJobsStorage__blobServiceUri |
存储帐户的 blob 服务的数据平面 URI,使用 HTTPS 方案。 | https://<storage_account_name>.blob.core.windows.net |
AzureWebJobsStorage__queueServiceUri |
存储帐户的队列服务的数据平面 URI,使用 HTTPS 方案。 | https://<storage_account_name>.queue.core.windows.net |
AzureWebJobsStorage__tableServiceUri |
存储帐户的表服务的数据平面 URI,使用 HTTPS 方案。 | https://<storage_account_name>.table.core.windows.net |
还可以设置基于标识的连接的通用属性。
如果使用将默认 DNS 后缀和服务名称用于全局 Azure 的存储帐户来配置 AzureWebJobsStorage
,则可以按照 https://<accountName>.[blob|queue|file|table].core.windows.net
格式将 AzureWebJobsStorage__accountName
设置为存储帐户的名称。 对于此帐户,将会推断每个存储服务的终结点。 如果存储帐户在主权云中或具有自定义 DNS,则此操作不起作用。
设置 | 说明 | 示例值 |
---|---|---|
AzureWebJobsStorage__accountName |
存储帐户的帐户名称,仅当帐户不在主权云中且没有自定义 DNS 时有效。 此语法是 AzureWebJobsStorage 独有的,不能用于其他基于标识的连接。 |
<storage_account_name> |
你将需要创建一个角色分配,以便在运行时提供对“AzureWebJobsStorage”存储帐户的访问权限。 所有者等管理角色还不够。 存储 Blob 数据所有者角色涵盖了 Functions 主机存储的基本需求 - 运行时需要具有对 Blob 的读写访问权限以及创建容器的能力。 多个扩展使用此连接作为 blob、队列和表的默认位置,此类用法可能会添加下表所述要求。 如果出于任何其他目的使用“AzureWebJobsStorage”,可能需要更多的权限。
分机 | 所需角色 | 说明 |
---|---|---|
没有扩展(仅主机) | 存储 Blob 数据所有者 | 用于常规协调,默认密钥存储 |
Azure Blob(仅触发器) | 所有: 存储帐户参与者、 存储 Blob 数据所有者、 存储队列数据参与者 |
blob 触发器在内部使用 Azure 队列并写入 blob 回执。 无论为触发器配置的连接如何,它都会使将 AzureWebJobsStorage 用于这些项。 |
Azure 事件中心(仅触发器) | (没有默认要求中的更改) 存储 Blob 数据所有者 |
使用 AzureWebJobsStorage 连接将检查点保存在 blob 中。 |
计时器触发器 | (没有默认要求中的更改) 存储 Blob 数据所有者 |
若要确保每个事件执行一次,请使用 AzureWebJobsStorage 连接对 blob 进行锁定。 |
Durable Functions | 所有: 存储 Blob 数据参与者、 存储队列数据参与者、 存储表数据参与者 |
Durable Functions 使用 blob、队列和表来协调活动函数和保持业务流程状态。 默认情况下,它将 AzureWebJobsStorage 连接用于所有这些项,但你可以在 Durable Functions 扩展配置中指定另一连接。 |
报告问题
项目 | 说明 | 链接 |
---|---|---|
运行时 | 脚本主机、触发器和绑定及语言支持 | 提出问题 |
模板 | 创建模板的代码问题 | 提出问题 |
门户 | 用户界面或体验问题 | 提出问题 |
开源存储库
Azure Functions 的代码是开源的,可以在以下 GitHub 存储库中找到关键组件:
后续步骤
有关详细信息,请参阅以下资源: