将编排生命周期事件发布到 Azure 事件网格,可以实现 DevOps 自动化(例如蓝/绿部署)、实时监控仪表板以及跟踪长时间运行的后台进程。
注意
本指南使用.NET示例,但概念和Azure CLI命令适用于所有受支持的Durable Functions语言。
Tip
如果已配置事件网格自定义主题和托管标识,请跳到 配置Durable Functions发布者应用。
先决条件
部署到Azure的Durable Functions项目。 如果没有,请使用首选语言的快速入门创建一个:
- C# (独立辅助角色模型) | JavaScript | Python | PowerShell | Java
正确的Durable Functions扩展版本。 对于.NET,请将扩展更新到最新版本:
2.7.0+ (进程内)
dotnet add package Microsoft.Azure.WebJobs.Extensions.DurableTask1.1.0+ (隔离工作者)
dotnet add package Microsoft.Azure.Functions.Worker.Extensions.DurableTask
对于其他语言,请检查你的
package.json、requirements.txt、pom.xml或requirements.psd1。在您的函数应用中启用和配置了托管身份。
一个 HTTP 测试工具 ,用于保护数据安全。
创建自定义事件网格主题
可以使用 Azure CLI、PowerShell 或 Azure 门户创建事件网格主题,以便从Durable Functions发送事件。
本指南使用Azure CLI。
创建资源组
使用 az group create 命令创建资源组。 选择支持事件网格的位置,并匹配要在其中部署资源的位置。
注意
目前,Azure 事件网格不支持所有区域。 有关支持哪些区域的信息,请参阅 Azure 事件网格 概述。
az group create --name <resource-group-name> --location <location>
启用事件网格资源提供者
如果这是首次在 Azure 订阅中使用事件网格,则可能需要注册事件网格资源提供程序。 运行以下命令,注册提供程序:
az provider register --namespace Microsoft.EventGrid完成注册可能需要一些时间。 若要查看状态,请运行以下命令:
az provider show --namespace Microsoft.EventGrid --query "registrationState"当
registrationState为Registered后,即可继续。
创建自定义主题
事件网格主题提供用户定义的终结点,可向该终结点发布事件。 在以下命令中将 <topic-name> 替换为您主题的唯一名称。 主题名称必须是唯一的,因为它将成为 DNS 条目。
az eventgrid topic create --name <topic-name> --location <location> --resource-group <resource-group-name>
获取主题终结点
获取主题的终结点。 将以下命令中的 <topic-name> 替换为您选择的名称。
az eventgrid topic show --name <topic-name> --resource-group <resource-group-name> --query "endpoint" --output tsv
保存此终结点供以后使用。
使用托管标识配置事件网格发布(建议)
Azure 中的托管标识允许资源在不存储凭据、简化安全性和标识管理的情况下向 Azure 服务进行身份验证。 将与 Durable Function 应用关联的托管标识分配给事件网格自定义主题。
配置Durable Functions发布者应用
尽管Durable Functions应用会自动将业务流程生命周期事件发布到事件网格,但需要配置连接设置。 将以下内容添加到 extensions.durableTask 以下 host.json部分中:
{
"version": "2.0",
"extensions": {
"durableTask": {
"eventGridTopicEndpoint": "%EventGrid__topicEndpoint%",
"eventGridKeySettingName": "EventGrid__credential"
}
}
}
注意
该 eventGridTopicEndpoint 设置引用前面保存的事件网格自定义主题终结点。 凭据设置可同时处理托管身份和连接字符串场景。
分配事件网格数据发送者角色
授予 托管标识 将事件发布到 Event Grid 主题的权限。
az role assignment create \
--assignee <client-id-of-managed-identity> \
--assignee-principal-type ServicePrincipal \
--role "EventGrid Data Sender" \
--scope /subscriptions/<subscription-id>/resourceGroups/<resource-group-name>/providers/Microsoft.EventGrid/topics/<topic-name>
请替换以下值:
-
<client-id-of-managed-identity>:用户分配的托管标识的客户端 ID -
<subscription-id>:Azure订阅 ID -
<resource-group-name>:包含事件网格主题的资源组的名称 -
<topic-name>:事件网格主题的名称
注意
角色分配可能需要 5-10 分钟才能传播。 如果在分配后马上进行操作,可能会看到身份验证错误。
配置应用设置
为函数应用和主题启用托管标识后,请在Durable Functions函数应用上配置事件网格应用设置。
添加以下应用设置:
-
EventGrid__topicEndpoint— 事件网格主题终结点。 -
EventGrid__credential— 设置为managedidentity. -
EventGrid__clientId— 用户分配的托管身份客户端 ID。
az functionapp config appsettings set --name <function app name> --resource-group <resource group name> --settings EventGrid__topicEndpoint="<topic endpoint>" EventGrid__credential="managedidentity" EventGrid__clientId="<client id>"
订阅活动
若要接收已发布的生命周期事件,请创建一个 事件网格订阅 ,用于将事件从自定义主题路由到订阅服务器。 常见的订阅服务器类型包括Azure Functions(包含事件网格触发器)、逻辑应用和 Webhook。
以下示例使用Azure CLI创建具有事件网格触发器的订阅服务器函数应用。 如果您已经有订阅者,请跳到 创建事件网格订阅。
创建侦听器函数应用
创建用于托管事件网格触发器的函数应用。 侦听器必须与事件网格主题位于同一区域。
# Create a resource group
az group create --name <listener-resource-group-name> --location <location>
# Create a storage account
az storage account create \
--name <storage-account-name> \
--resource-group <listener-resource-group-name> \
--location <location> \
--sku Standard_LRS \
--allow-blob-public-access false
# Create the function app
az functionapp create \
--resource-group <listener-resource-group-name> \
--consumption-plan-location <location> \
--runtime <preferred-runtime> \
--functions-version 4 \
--name <listener-function-app-name> \
--storage-account <storage-account-name>
创建和部署事件网格触发器函数
搭建本地项目、添加事件网格触发器并发布它:
mkdir EventGridListenerFunction && cd EventGridListenerFunction
func init --name EventGridListener --runtime dotnet-isolated
func new --template "Event Grid trigger" --name EventGridTrigger
func azure functionapp publish <listener-function-app-name>
注意
将 dotnet-isolated 替换为您首选的运行时(node、python、java 或 powershell). 有关详细的部署说明,请参阅 Publish 到 Azure。
创建事件网格订阅
使用 azurefunction 终结点类型创建订阅,该类型会自动处理 Webhook 验证:
az eventgrid event-subscription create \
--name <subscription-name> \
--source-resource-id /subscriptions/<subscription-id>/resourceGroups/<resource-group-name>/providers/Microsoft.EventGrid/topics/<topic-name> \
--endpoint /subscriptions/<subscription-id>/resourceGroups/<listener-resource-group-name>/providers/Microsoft.Web/sites/<listener-function-app-name>/functions/EventGridTrigger \
--endpoint-type azurefunction
Tip
建议将 --endpoint-type azurefunction 与函数的资源 ID 一起使用。 它能够自动处理 Webhook 的验证,比使用带有 URL 的 --endpoint-type webhook 更加可靠。
事件架构
当业务流程状态发生更改时,Durable Functions运行时会发布具有以下结构的事件。 为每个状态转换自动生成事件 - 无需添加任何代码。
| 领域 | 说明 |
|---|---|
id |
事件网格事件的唯一标识符。 |
subject |
durable/orchestrator/{orchestrationRuntimeStatus}— 状态可以是Running、Completed或FailedTerminated。 |
eventType |
始终为 orchestratorEvent。 |
eventTime |
事件时间(UTC)。 |
data.hubName |
TaskHub 名称。 |
data.functionName |
Orchestrator 函数名称。 |
data.instanceId |
唯一的编排实例 ID。 |
data.runtimeStatus |
Running、 Completed、 Failed或 Canceled. |
data.reason |
其他跟踪数据。 有关详细信息,请参阅 Durable Functions 中的 Diagnostics。 |
事件网格可确保至少传递一次,因此你可能会在极少数故障情况下收到重复事件。 请考虑根据需要添加 instanceId 去重逻辑。
验证事件传递
若要验证端到端设置,请部署 Durable Functions 应用并触发一次协调运行:
发布函数代码到Azure,然后验证函数应用在Azure门户中显示“正在运行”。
在 Azure 门户中,在 设置>环境变量 下验证你的应用设置
EventGrid__topicEndpoint和(如果使用托管身份)EventGrid__credential。使用 HTTP 客户端触发编排流程:
curl -X POST https://<function_app_name>.chinacloudsites.cn/api/HelloOrchestration_HttpStart在 Azure 门户中,导航到 listener 函数应用>EventGridTrigger>Monitor以查看收到的事件。 你应该会看到主题类似于
durable/orchestrator/Running和durable/orchestrator/Completed的事件。
在 Application Insights 中验证(可选)
若需更全面的视图,请在函数应用的 Application Insights 日志中运行此 KQL 查询。
traces
| where message contains "Event type" or message contains "Event subject"
| project timestamp, message
| order by timestamp desc
故障排除
事件未发布到事件网格
问题:侦听器函数未接收事件。
解决方法:
- 验证Durable Functions函数应用是否具有正确的应用设置:
-
EventGrid__topicEndpoint必须指向自定义主题终结点 -
EventGrid__credential必须设置为managedidentity -
EventGrid__clientId如果使用用户分配的标识,则必须设置
-
- 验证托管标识是否具有分配给事件网格自定义主题的 EventGrid 数据发送者 角色。
- 检查 Application Insights 中的Durable Functions函数应用日志是否存在错误。
- 验证事件网格主题是否存在并且在同一订阅中可访问。
未触发监听器函数
问题:侦听器函数存在,但在发布事件时未执行。
解决方法:
- 验证是否已创建事件网格订阅并已启用:
- 在 Azure 门户中,导航到事件网格主题 → Subscriptions
- 确认侦听器函数的订阅状态 已列出为“已启用”
- 验证事件网格订阅是否使用正确的终结点类型:
- 对于 Azure Functions,请结合函数的资源 ID 使用
--endpoint-type azurefunction - 如果使用
--endpoint-type webhook,请确保 Webhook URL 格式正确:https://<function-app>.chinacloudsites.cn/runtime/webhooks/eventgrid?functionName=<function-name>&code=<system-key>
- 对于 Azure Functions,请结合函数的资源 ID 使用
- 检查侦听器函数应用日志中是否存在错误或传递问题。
- 在事件网格主题→ 指标中,检查是否存在可能指示传递失败的 已删除事件 。
日志中的“禁止访问”或身份验证错误
问题:发布到事件网格时的身份验证错误。
解决方法:
- 验证托管身份是否已正确配置并在 Durable Functions 函数应用上启用:
- 在 Azure 门户中,导航到函数应用 → Identity
- 请确认“状态”显示为 开启,无论是系统分配标识还是用户分配标识。
- 验证角色分配是否正确:
- 导航到您的事件网格主题 → 访问控制(IAM)
- 确认托管标识具备 EventGrid 数据发送方 角色(注意:“Event”和“Grid”之间无空格)
- 角色分配可能需要 5-10 分钟才能生效
“连接被拒绝”或“找不到终结点”错误
问题:事件网格主题的连接错误。
解决方法:
- 验证应用设置中的事件网格主题终结点是否正确,并包含完整的 URL(例如)
https://my-topic.eventgrid.chinacloudapi.cn/api/events - 验证同一订阅和区域中是否存在事件网格主题资源
- 检查Durable Functions应用是否对事件网格终结点具有网络访问权限
在本地测试
若要在本地进行测试,请参阅 使用查看器 Web 应用的本地测试。 使用托管标识在本地测试时,请使用开发人员凭据对事件网格主题进行身份验证。 有关详细信息,请参阅 使用托管标识配置Durable Functions - 本地开发。
清理资源
如果不打算继续使用本教程中创建的资源,请将其删除以避免产生费用。
删除资源组
删除资源组及其包含的所有资源:
az group delete --name <resource-group-name> --yes
az group delete --name <listener-resource-group-name> --yes
删除单个资源
如果要保留某些资源,可以单独删除它们:
删除事件网格订阅:
az eventgrid event-subscription delete \ --name <subscription-name> \ --source-resource-id /subscriptions/<subscription-id>/resourceGroups/<resource-group-name>/providers/Microsoft.EventGrid/topics/<topic-name>删除事件网格主题:
az eventgrid topic delete --name <topic-name> --resource-group <resource-group-name>删除函数应用:
az functionapp delete --name <publisher-function-app-name> --resource-group <resource-group-name> az functionapp delete --name <listener-function-app-name> --resource-group <listener-resource-group-name>删除存储帐户:
az storage account delete --name <storage-account-name> --resource-group <resource-group-name> --yes az storage account delete --name <listener-storage-account-name> --resource-group <listener-resource-group-name> --yes
后续步骤
了解有关以下方面的详细信息:
- 实例管理
- Durable Functions 中的版本控制