快速入門:建立一個使用 MSSQL 儲存服務的 Durable Functions 應用程式

利用 Azure Functions 的功能 Durable Functions,在無伺服器環境中撰寫具狀態的函式。 Durable Functions 管理應用程式中的狀態、檢查點和重啟。

Durable Functions 支援多個儲存供應者,也就是所謂的後端,用於儲存協調處理和實體運行時狀態。 在這個快速入門中,你會建立一個 Durable Functions 應用程式,它使用 Microsoft SQL Server(MSSQL)儲存提供者,並搭配 Visual Studio Code。

本快速入門會建立一個 .NET (隔離式模型) 應用程式,作為示範用途。 這些概念在其他語言中也有類似的應用。

Tip

如果你已經有 SQL Server 實例,想跳過本地資料庫設定,可以直接到 Add SQL 連接字串到 local.settings.json。

Note

不支援跨儲存供應商遷移 任務中心資料 。 擁有現有執行時資料的函式應用程式,切換到 MSSQL 後端後,會從一個全新且空白的任務中心開始。

先決條件

若要完成本快速入門,您需要:

建立 Azure Functions 專案

在 Visual Studio Code 中,建立一個本地的 Azure Functions 專案。

  1. 在 [檢視] 功能表上,選取 [命令選擇區] (或選取 Ctrl+Shift+P)。

  2. 在提示(>)時,輸入並選擇 Azure Functions:建立新專案。

    Visual Studio Code 中指令面板的截圖,顯示建立函式專案的選項。

  3. 選擇 瀏覽。 在 [選取資料夾] 對話框中,移至要用於您專案的資料夾,然後選擇 [選取]。

  4. 在提示中,選取或輸入下列值:

    Prompt 動作 Description
    為您的函式應用程式專案選取語言 選擇 .NET 建立本機 C# Functions 專案
    選擇 .NET 執行階段 選擇.NET 8.0 isolated。 建立一個 Functions 專案,支援在獨立工作程序中運行的 .NET 8 及 Azure Functions Runtime 4.0。
    為專案的第一個函式選取範本 選取 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 傳回您好的簡單函數應用程式。 此函式包含要進行協調的商務邏輯。
HelloOrchestration_HttpStart HTTP 觸發的函式,該函式會啟動協調流程執行個體並傳回檢查狀態回應。

欲了解更多這些函數,請參見 Durable Functions 類型與特徵。

設定您的資料庫

這個快速啟動使用了一個 SQL Server Docker 映像。 關於替代方案(SQL Server Express、Azure SQL Database 或本地實例),請參閱 storage provider overview。

Note

如果你已經有相容 MSSQL 的資料庫,可以跳到 將 SQL 連接字串 加入 local.settings.json。

建立你本地的 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,並在連接埠 1433 上接聽。 如果埠 1433 與其他服務衝突,請在將變數 $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

Note

若要停止和刪除執行中的容器,您可以分別使用 docker stop <containerName> 和 docker rm <containerName>。 您可以使用這些命令來重新建立容器,並在您完成本快速入門之後停止該容器。 如需更多協助,請執行 docker --help。

Troubleshooting

如果您在執行 以docker exec資料庫時遇到「精靈的錯誤回應:OCI 運行時間 exec 失敗」,則資料夾/opt/mssql-tools/bin/sqlcmd可能不存在。 打開 Docker 桌面,選擇你的 SQL Server Docker 容器,選擇檔案,然後瀏覽 mssql-tools 資料夾。 檢查此資料夾是否有其他名稱,例如 /opt/mssql-tools18/bin/sqlcmd。 請據以更新命令。

在 ODBC Driver 18 for SQL Server 中,[加密連線] 選項預設會設定為 true。 如果您在執行 執行資料庫作業時遇到 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 伺服器實例的 連接字串 指派給 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 是執行任何函式應用程式所需的 Azure 記憶體模擬器。

在應用程式的根資料夾中開啟另一個終端機視窗,然後執行 func host start來啟動函式應用程式。

  1. 在終端機視窗中,複製 HTTP 觸發函式的 URL 端點。

    Azure Functions本地輸出視窗截圖,顯示 HTTP 觸發函式 URL 端點。

  2. 使用 HTTP 測試工具,將 HTTP POST 要求傳送至 URL 端點。

    回應是 HTTP 函式的初始結果。 它可讓您知道 Durable Functions 協調流程已成功啟動。 其尚未顯示協調流程的最終結果。 回應包含一些實用的 URL。

  3. 複製 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,這需要額外資源與設定。

Important

如果您的應用程式托管在 Flex Consumption 方案 上,則不支援對 Azure SQL Database 的管理身份驗證。 改用 連接字串 搭配 SQL 認證。 若想在無伺服器方案中支援管理身份,請考慮使用 Durable Task Scheduler。

要在 Azure 中執行你的應用程式,你需要建立各種資源。 為了方便日後清理,將所有資源建立在同一個資源群組中。

建立 Azure SQL 資料庫

Note

如果你已經有一個 Azure SQL 資料庫或其他公開可存取的 SQL Server 實例想使用,可以前往下一節。

避免啟用 允許 Azure 服務與資源存取此 [SQL] 伺服器設定以用於生產情境。 實際應用程式應該實作更安全的方法,例如更強大的防火牆限制或虛擬網路設定。

在Azure入口網站中,你可以建立Azure SQL資料庫。 創建過程中:

  • 啟用 Azure 服務與資源來存取此伺服器(在 [網路] 下)
  • 將 資料庫排序規則 的值(在 附加設定 中)設定為 Latin1_General_100_BIN2_UTF8。

建立 Azure Functions 應用程式和支持資源

  1. 開啟終端機視窗並登入 Azure:

    az login
    
  2. 在與 SQL 資料庫相同的資源群組和區域中建立下列資源:

    • 一般用途的記憶體帳戶,用來儲存重要的應用程式數據,例如應用程式程序代碼本身。 記憶體帳戶名稱必須包含三到 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 Database 的存取權

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 Database

管理身份需要兩個授權:db_owner在您的應用程式資料庫中(用於建立和管理任務中心架構),以及dbmanager與master資料庫中(用於允許啟動時進行資料庫層級操作)。

Note

在 Flex Consumption 方案中託管 Durable Functions 應用程式時,不支援使用 managed identity 進行 Azure SQL 資料庫的驗證。 如果您的應用程式裝載於 Flex Consumption 方案中,請跳至 [設定應用程式設定 ] 區段。

  1. 首先,將開發人員身分識別設定為資料庫的系統管理員。

    受託人是您的身分識別,因此請變更為您的電子郵件:

    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"
    
  2. 連接先前使用 SQL Management Server Studio 或 Visual Studio Code 等工具建立的 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
    
  3. 連接到 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:受控識別的 ClientId
  • AzureWebJobsStorage__credential:認證類型,這是 managedidentity
  • SQLDB_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 資料庫資源,進入 Settings 標籤,然後點選 Connection strings 找到它:

Azure入口網站中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 SQL 查詢編輯器 的 SQL 查詢結果。

下一步