使用 Durable Functions(Azure Functions 的一项功能)在无服务器环境中编写有状态函数。 Durable Functions 管理应用程序中的状态、检查点和重启。
Durable Functions 支持多个 存储提供程序(也称为 后端),用于存储业务流程和实体运行时状态。 在本快速入门中,你将创建一个 Durable Functions 应用,以使用 Microsoft SQL Server (MSSQL) 存储提供程序,并使用 Visual Studio Code。
本快速启动创建演示用的 .NET(独立模型)应用程序。 本文中提供的内容以类似的方式适用于其他语言。
注意
MSSQL 后端旨在最大程度地提高应用程序可移植性和对数据的控制。 它使用 Microsoft SQL Server 来保存所有任务中心数据,以便用户获得现代企业级数据库管理系统 (DBMS) 基础结构的优势。 若要详细了解何时使用 MSSQL 存储提供程序,请参阅存储提供程序概述。
目前不支持跨存储提供程序迁移任务中心数据。 具有现有的运行时数据的函数应用在切换到 MSSQL 后端后,会从新的空任务中心开始。 同样,如果切换到其他存储提供程序,则使用 MSSQL 创建的任务中心内容无法保留。
先决条件
若要完成本快速入门指南,你需要:
已安装 Visual Studio Code。
已安装最新版本的 Azure Functions Core Tools。
已安装 .NET 8.0 SDK。
已安装 Docker。
一个 Azure 订阅。
一个 HTTP 测试工具,用于保护数据安全。 有关详细信息,请参阅 HTTP 测试工具。
创建 Azure Functions 项目
在 Visual Studio Code 中,创建本地 Azure Functions 项目。
在“视图”菜单上选择“命令面板”(或选择 Ctrl+Shift+P)。
在提示符 (
>
) 处输入然后选择“Azure Functions: 创建新项目”。选择“浏览”。 在“选择文件夹”对话框中,转到要用于项目的文件夹,然后选择“选择”。
在提示符处,选择或输入以下值:
提示 行动 DESCRIPTION 选择用于您的函数应用程序项目的语言 选择 .NET 创建本地 C# Functions 项目 选择 .NET 运行时 选择“.NET 8.0 独立”。 创建一个支持在独立工作进程和 Azure Functions 运行时 4.0 中运行的 .NET 8 的 Functions 项目。 为项目的第一个函数选择模板 选择“Durable Functions 业务流程”。 创建 Durable Functions 业务流程 选择持久存储类型 选择 MSSQL。 选择 MSSQL 存储提供程序。 提供函数名称 输入 HelloOrchestration。 业务流程函数的名称。 提供命名空间 输入 Company.Function。 所生成类的命名空间。 选择打开项目的方式 选择“在当前窗口中打开”。 在所选的文件夹中打开 Visual Studio Code。
如果需要创建项目,Visual Studio Code 会安装 Azure Functions Core Tools。 它还会在某个文件夹中创建一个函数应用项目。 此项目包含 host.json 和 local.settings.json 配置文件。
另一个文件 (HelloOrchestration.cs) 包含 Durable Functions 应用的基本构建基块:
方法 | DESCRIPTION |
---|---|
HelloOrchestration |
定义 Durable Functions 应用业务流程。 在此示例中,业务流程启动,创建一个列表,然后将三个函数调用的结果添加到列表中。 当三个函数调用完成后,它返回该列表。 |
SayHello |
返回“hello”的简单函数应用。 此函数包含编排的业务逻辑。 |
HelloOrchestration_HttpStart |
HTTP 触发的函数,用于启动业务流程的实例并返回检查状态响应。 |
有关这些函数的详细信息,请参阅 Durable Functions 类型和功能。
设置数据库
注意
如果你已有与 MSSQL 兼容的数据库,则可以跳过本节以及有关设置基于 Docker 的本地数据库的下一节。
由于 MSSQL 后端旨在实现可移植性,因此可以使用多个选项来设置备份数据库。 例如,可以设置本地 SQL Server 实例、使用完全托管的 Azure SQL Database 实例,或使用任何其他 SQL Server 兼容的托管选项。
还可以在本地 Windows 计算机上使用 SQL Server Express 进行本地脱机开发,或使用在 Docker 容器中运行的 SQL Server Docker 映像。
本快速入门重点介绍如何使用 SQL Server Docker 映像。
设置本地基于 Docker 的 SQL Server 实例
使用以下 PowerShell 命令在 Docker 上设置本地 SQL Server 数据库。 可以在 Windows、macOS 或 Linux 上安装 PowerShell。
# primary parameters
$pw = "yourStrong(!)Password"
$edition = "Developer"
$port = 1433
$tag = "2019-latest"
$dbname = "DurableDB"
$collation = "Latin1_General_100_BIN2_UTF8"
# pull the image from the Microsoft container registry
docker pull mcr.microsoft.com/mssql/server:$tag
# run the image and provide some basic setup parameters
docker run --name mssql-server -e 'ACCEPT_EULA=Y' -e "MSSQL_SA_PASSWORD=$pw" -e "MSSQL_PID=$edition" -p ${port}:1433 -d mcr.microsoft.com/mssql/server:$tag
# wait a few seconds for the container to start...
# create the database with strict binary collation
docker exec -it mssql-server /opt/mssql-tools/bin/sqlcmd -S . -U sa -P "$pw" -Q "CREATE DATABASE [$dbname] COLLATE $collation"
# if sqlcmd is in the mssql-tools18 folder
# docker exec -it mssql-server /opt/mssql-tools18/bin/sqlcmd -C -S . -U sa -P "$pw" -Q "CREATE DATABASE [$dbname] COLLATE $collation"
现在,应在 Docker 上运行本地 SQL Server 并侦听端口 1443
。 如果端口 1443
与其他服务冲突,在将变量 $port
更改为其他值后重新运行这些命令。
若要验证数据库安装,请查询新的 SQL 数据库:
docker exec -it mssql-server /opt/mssql-tools/bin/sqlcmd -S . -U sa -P "$pw" -Q "SELECT name FROM sys.databases"
如果数据库设置成功完成,数据库的名称(例如 DurableDB)将显示在命令行输出中:
name
--------------------------------------------------------------
master
tempdb
model
msdb
DurableDB
注意
若要停止和删除正在运行的容器,可以分别使用 docker stop <containerName>
和 docker rm <containerName>
。 可以使用这些命令重新创建容器,并在完成本快速入门后停止容器。 如需更多帮助,请运行 docker --help
。
故障排除
如果在运行docker exec
时遇到“守护程序的错误响应:OCI 运行时 exec 失败”,则可能是文件夹/opt/mssql-tools/bin/sqlcmd
不存在。 打开 Docker Desktop,选择 SQL Server Docker 容器,选择“文件”并浏览 mssql-tools 文件夹。 检查此文件夹是否具有其他名称,例如 /opt/mssql-tools18/bin/sqlcmd
。 相应地更新命令。
在 ODBC Driver 18 for SQL Server 中,“加密连接”选项默认设置为 true。 如果在运行 以执行数据库操作时遇到“error:1416F086:SSL 例程:tls_process_server_certificate:certificate verify failed:self signed certificate”docker exec
,则追加 -C
,这相当于 ADO.net 选项 TRUSTSERVERCERTIFICATE = true
。
将 SQL 连接字符串添加到 local.settings.json
MSSQL 后端需要连接字符串才能访问数据库。 获取连接字符串的方式主要取决于特定的 MSSQL 服务器提供程序。
如果使用上述 Docker 命令而不更改任何参数,则连接字符串为:
Server=localhost,1433;Database=DurableDB;User Id=sa;Password=yourStrong(!)Password;
在 local.settings.json中,将基于 Docker 的 SQL Server 实例的连接字符串分配给 SQLDB_Connection
。 选择 MSSQL 作为 Durable Functions 应用的后端时,Visual Studio Code 添加了此变量:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"SQLDB_Connection": "Server=localhost,1433;Database=DurableDB;User Id=sa;Password=yourStrong(!)Password;",
"FUNCTIONS_WORKER_RUNTIME": "<dependent on your programming language>"
}
}
本地测试
在应用的根文件夹中打开终端窗口并运行 azurite start
。 Azurite 是运行任何 Function App 所需的 Azure 存储模拟器。
在应用的根文件夹中打开另一个终端窗口,并通过运行 func host start
启动函数应用。
在终端窗口中,复制 HTTP 触发的函数的 URL 终结点。
使用 HTTP 测试工具向 URL 终结点发送 HTTP POST 请求。
响应是 HTTP 函数的初始结果。 它让你知道 Durable Functions 业务流程已成功启动。 它尚未显示编排的最终结果。 响应中包括了几个有用的 URL。
复制
statusQueryGetUri
的 URL 值,将其粘贴到浏览器的地址栏中,然后执行请求。 或者也可以继续使用 HTTP 测试工具发出 GET 请求。请求将查询业务流程实例的状态。 应该会看到实例已完成,并且它包含 Durable Functions 应用的输出或结果,如以下示例所示:
{ "name":"HelloCities", "instanceId":"7f99f9474a6641438e5c7169b7ecb3f2", "runtimeStatus":"Completed", "input":null, "customStatus":null, "output":"Hello, Tokyo! Hello, London! Hello, Seattle!", "createdTime":"2023-01-31T18:48:49Z", "lastUpdatedTime":"2023-01-31T18:48:56Z" }
在 Azure 中运行应用
若要在 Azure 中运行应用,需要创建各种资源。 为了方便以后进行清理,请在同一资源组中创建所有资源。
创建 Azure SQL 数据库
注意
如果你已有 Azure SQL 数据库或者你想使用的其他可公开访问的 SQL Server 实例,则可以转到下一节。
不要为生产方案启用 允许 Azure 服务和资源访问此 [SQL] 服务器 设置。 实际应用程序应实现更安全的方法,例如更强的防火墙限制或虚拟网络配置。
在 Azure 门户中,可以创建 Azure SQL 数据库。 在创建过程中:
- 启用 Azure 服务和资源以访问此服务器(在 网络下)
- 将 数据库排序规则 的值(在 “其他设置”下)设置为
Latin1_General_100_BIN2_UTF8
。
创建 Azure Functions 应用和支持资源
打开终端窗口并登录到 Azure:
az login
在 SQL 数据库所在的同一资源组和区域中创建以下资源:
- 常规用途存储帐户,用于存储重要的应用数据,例如应用程序代码本身。 存储帐户名称必须仅包含 3 到 24 个字符的数字和小写字母。
- 高级函数应用计划
- 功能性应用程序
# Variables ___location=<REGION> resourceGroup=<RESOURCE_GROUP_NAME> storage=<STORAGE_NAME> planName=<PREMIUM_PLAN_NAME> functionApp=<APP_NAME> skuStorage="Standard_LRS" skuPlan="EP1" functionsVersion="4" # Create an Azure storage account echo "Creating $storage" az storage account create --name $storage --___location "$___location" --resource-group $resourceGroup --sku $skuStorage --allow-blob-public-access false # Create a premium plan echo "Creating $premiumPlan" az functionapp plan create --name $planName --resource-group $resourceGroup --___location "$___location" --sku $skuPlan # Create a function app hosted in the premium plan echo "Creating $functionApp" az functionapp create --name $functionApp --storage-account $storage --plan $planName --resource-group $resourceGroup --functions-version $functionsVersion
创建 Azure 托管标识
托管标识通过消除应用中的机密(例如连接字符串中的凭据)使应用更安全。 可以在 系统分配的托管标识和用户分配的托管标识之间进行选择。 本快速入门演示如何设置用户分配的托管标识,这是建议的选项,因为它未绑定到应用生命周期。
以下命令创建标识资源并将其分配给应用:
# Variables
subscription=<SUBSCRIPTION_ID>
identity=<IDENTITY_NAME>
# Create a managed identity resource
echo "Creating $identity"
az identity create -g $resourceGroup -n $identity --___location "$___location"
# Construct the identity resource ID
resourceId="/subscriptions/$subscription/resourceGroups/$resourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/$identity"
# Assign the identity to the Azure Functions app
echo "Assigning $identity to app"
az functionapp identity assign -g $resourceGroup -n $functionApp --identities "$resourceId"
# Get the identity's ClientId and PrincipalId (also called ObjectId) for a later step.
clientId=$(az identity show --name $identity --resource-group $resourceGroup --query 'clientId' --output tsv)
principalId=$(az identity show --name $identity --resource-group $resourceGroup --query 'principalId' --output tsv)
授予对 Azure 存储和 Azure SQL 数据库的访问权限
Azure 存储
分配“存储 Blob 数据所有者”标识角色以访问存储帐户。
# Set the scope of the access
scope="/subscriptions/$subscription/resourceGroups/$resourceGroup/providers/Microsoft.Storage/storageAccounts/$storage"
# Assign the role
echo "Assign Storage Blob Data Owner role to identity"
az role assignment create --assignee "$clientId" --role "Storage Blob Data Owner" --scope "$scope"
Azure SQL 数据库
注意
在 Flex Consumption 计划中托管 Durable Functions 应用时, 不支持 使用托管标识对 Azure SQL 数据库进行身份验证。 如果应用托管在 Flex Consumption 计划中,请跳到 “设置应用设置” 部分。
首先将开发人员标识设置为数据库的管理员。
被分配人是你的标识,因此请更改为你的电子邮件:
assignee=$(az ad user show --id "someone@example.com" --query "id" --output tsv)
将被分配者设置为 Azure SQL 数据库的管理员:
az sql server ad-admin create --resource-group $resourceGroup --server-name <SQL_SERVER_NAME> --display-name ADMIN --object-id "$assignee"
连接到以前使用 Azure Data Studio 或 SQL Management Server Studio 等工具创建的 SQL 数据库。 或者,可以运行以下 SQLCMD 命令进行连接:
sqlcmd -S <SQL_SERVER_NAME>.database.windows.net -d <DATABASE_NAME> -U <someone@example.com> -P "ACCOUNT_PASSWORD" -G -l 30
通过针对数据库运行以下查询,授予标识 db_owner 访问权限。
IDENTITY_OBJECT_ID
这是标识创建步骤中的 PrincipalId。CREATE USER "<IDENTITY_NAME>" FROM EXTERNAL PROVIDER With OBJECT_ID='<IDENTITY_OBJECT_ID>' ALTER ROLE db_owner ADD MEMBER "<IDENTITY_NAME>"; GO
连接到
master
数据库并授予标识 dbmanager 访问权限:CREATE USER "<IDENTITY_NAME>" FROM EXTERNAL PROVIDER With OBJECT_ID='<IDENTITY_OBJECT_ID>' ALTER ROLE dbmanager ADD MEMBER "<IDENTITY_NAME>"; GO
设置所需的应用设置
需要将以下应用设置添加到应用:
AzureWebJobsStorage__accountName
:Azure 存储帐户名称AzureWebJobsStorage__clientId
:托管标识的 ClientIdAzureWebJobsStorage__credential
:凭据类型为managedidentitySQLDB_Connection
:SQL 数据库连接字符串
如果使用用户分配的托管标识对 SQL 数据库进行身份验证,连接字符串应如下所示:
dbserver=<SQL_SERVER_NAME>
sqlDB=<SQL_DB_NAME>
clientId=<IDENTITY_CLIENT_ID>
sqlconnstr="Server=tcp:$dbserver.database.windows.net,1433;Initial Catalog=$sqlDB;Persist Security Info=False;User ID=$clientId;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Authentication='Active Directory Managed Identity';"
对于 Flex Consumption 应用,请立即使用连接字符串进行身份验证。 可以通过转到 Azure 门户上的 SQL 数据库资源,导航到 “设置” 选项卡,然后单击 连接字符串来找到它:
连接字符串应采用以下格式:
dbserver=<SQL_SERVER_NAME>
sqlDB=<SQL_DB_NAME>
username=<DB_USER_LOGIN>
password=<DB_USER_PASSWORD>
sqlconnstr="Server=tcp:$dbserver.database.windows.net,1433;Initial Catalog=$sqlDB;Persist Security Info=False;User ID=$username;Password=$password;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
运行以下命令以设置设置:
az functionapp config appsettings set --name $functionApp --resource-group $resourceGroup --settings AzureWebJobsStorage__accountName="$storage" AzureWebJobsStorage__clientId="$clientId" AzureWebJobsStorage__credential="managedidentity" SQLDB_Connection=$sqlconnstr
删除现有 AzureWebJobsStorage
设置:
az functionapp config appsettings delete --name $functionApp --resource-group $resourceGroup --setting-names "AzureWebJobsStorage"
将本地项目部署到 Azure 并测试
最后,在根项目文件夹中,通过运行以下命令将应用部署到 Azure:
func azure functionapp publish $functionApp
部署完成后,运行以下命令以获取 HTTP 触发器 URL:
az functionapp function list --resource-group $resourceGroup --name $functionApp --query '[].{Function:name, URL:invokeUrlTemplate}' --output json
使用 HTTP 测试工具进行测试,就像在本地开发期间一样。
还可以通过查询数据库来验证 MSSQL 后端是否正确配置了任务中心数据。
例如,可以在 SQL 数据库的概述窗格中查询你的业务流程实例。 选择“查询编辑器”,进行身份验证,然后运行以下查询:
SELECT TOP 5 InstanceID, RuntimeStatus, CreatedTime, CompletedTime FROM dt.Instances
运行简单的业务流程协调程序后,你应会看到至少一个结果,如以下示例所示:
后续步骤
- 在 Azure 容器应用中使用 MSSQL 后端托管 Durable Functions 应用。
- 有关此后端的体系结构、配置和工作负荷行为的详细信息,请参阅 MSSQL 存储提供程序文档 。