在這個快速入門中,你將使用 Azure Developer 命令列工具,建立一個無伺服器的工作流程,協調多個並行執行的任務。 你在 Azure 建立資源,在本地驗證程式碼,然後部署到一個新的無伺服器函式應用程式,該應用程式在 Azure Functions 的 Flex Consumption 計畫中運行。
這個專案使用 Azure Developer CLI (azd) 來簡化部署你的程式碼到 Azure。 此部署遵循目前安全且可擴展的 Azure Functions 部署最佳實務。 這個快速入門說明了扇出/扇入模式在 Durable Functions 中的應用,該擴充套件能協調有狀態的工作流程與持久執行。 範例使用 Durable Task Scheduler,一個完全受控的 Durable Functions 後端,取代了 Azure 儲存體 的後端。 這個範例並行取得文章標題 - 編排過程會擴展到多個同時運行的活動,然後再回到這些活動中聚合結果。
預設情況下,Flex Consumption 方案採用按 使用量付費 的計費模式,這表示完成此快速啟動會在你的 Azure 帳戶中產生幾美元或更少的費用。
先決條件
一個有有效訂閱的 Azure 帳號。 免費註冊帳號。
初始化專案
使用 azd init 指令,從範本建立本地 Durable Functions 程式碼專案。
在您的本機終端機或命令提示字元中,於空白資料夾中執行此
azd init命令:azd init --template durable-functions-quickstart-dotnet-azd -e dfquickstart-dotnet此指令會從 template 儲存庫拉取專案檔案,並在新資料夾中初始化專案。
-e旗標會設定目前環境的名稱。 在azd中,環境會為你的應用程式維持獨特的部署上下文,你可以定義多個。 環境名稱也會用在你在 Azure 建立的資源群組名稱中。切換到專案目錄,然後導航到應用程式資料夾:
fanoutfanincd durable-functions-quickstart-dotnet-azd/fanoutfanin
在您的本機終端機或命令提示字元中,於空白資料夾中執行此
azd init命令:azd init --template durable-functions-quickstart-python-azd -e dfquickstart-python此指令會從 template 儲存庫拉取專案檔案,並在新資料夾中初始化專案。
-e旗標會設定目前環境的名稱。 在azd中,環境會為你的應用程式維持獨特的部署上下文,你可以定義多個。 環境名稱也會用在你在 Azure 建立的資源群組名稱中。切換到專案目錄,然後導航到應用程式資料夾:
srccd durable-functions-quickstart-python-azd/src
在您的本機終端機或命令提示字元中,於空白資料夾中執行此
azd init命令:azd init --template durable-functions-quickstart-typescript-azd -e dfquickstart-typescript此指令會從 template 儲存庫拉取專案檔案,並在新資料夾中初始化專案。
-e旗標會設定目前環境的名稱。 在azd中,環境會為你的應用程式維持獨特的部署上下文,你可以定義多個。 環境名稱也會用在你在 Azure 建立的資源群組名稱中。切換到專案目錄,然後導航到應用程式資料夾:
srccd durable-functions-quickstart-typescript-azd/src
在您的本機終端機或命令提示字元中,於空白資料夾中執行此
azd init命令:azd init --template durable-functions-quickstart-java-azd -e dfquickstart-java此指令會從 template 儲存庫拉取專案檔案,並在新資料夾中初始化專案。
-e旗標會設定目前環境的名稱。 在azd中,環境會為你的應用程式維持獨特的部署上下文,你可以定義多個。 環境名稱也會用在你在 Azure 建立的資源群組名稱中。變更為專案目錄:
cd durable-functions-quickstart-java-azd
在您的本機終端機或命令提示字元中,於空白資料夾中執行此
azd init命令:azd init --template durable-functions-quickstart-javascript-azd -e dfquickstart-javascript此指令會從 template 儲存庫拉取專案檔案,並在新資料夾中初始化專案。
-e旗標會設定目前環境的名稱。 在azd中,環境會為你的應用程式維持獨特的部署上下文,你可以定義多個。 環境名稱也會用在你在 Azure 建立的資源群組名稱中。切換到專案目錄,然後導航到應用程式資料夾:
srccd durable-functions-quickstart-javascript-azd/src
在您的本機終端機或命令提示字元中,於空白資料夾中執行此
azd init命令:azd init --template durable-functions-quickstart-powershell-azd -e dfquickstart-powershell此指令會從 template 儲存庫拉取專案檔案,並在新資料夾中初始化專案。
-e旗標會設定目前環境的名稱。 在azd中,環境會為你的應用程式維持獨特的部署上下文,你可以定義多個。 環境名稱也會用在你在 Azure 建立的資源群組名稱中。切換到專案目錄,然後導航到應用程式資料夾:
srccd durable-functions-quickstart-powershell-azd/src
佈建 Azure 資源
本專案使用該azd provision指令建立所需的 Azure 資源,包括在 Flex Consumption 計畫中新增的功能應用程式、一個持久任務排程器,以及一個任務中心。
Tip
專案包含一組 Bicep 檔案 (位於 infra 資料夾),azd 會使用這些檔案,在符合最佳做法的彈性使用量方案上建立安全的部署。
回到根專案資料夾(包含該
azure.yaml檔案的資料夾):cd ..
- 確定你還在根專案資料夾(包含檔案
azure.yaml的資料夾)裡。
執行這個指令來用你的 Azure 帳號進行認證:
azd auth login從根專案資料夾執行此指令,建立
azd所需的 Azure 資源:azd provision根資料夾包含
azure.yaml所需的azd定義檔。當被要求時,提供以下必要的部署參數:
參數 Description Azure 訂用帳戶 建立您資源所在位置的訂用帳戶。 如果您的帳戶有多個租戶,您必須先選擇租戶。 Azure 位置 Azure 區域,用來建立包含新 Azure 資源的資源群組。 僅顯示目前支援彈性消費方案的地區。 vnetEnabled 是否要部署在虛擬網路中。 在本快速入門中,請選擇 false。 這個
azd provision指令會利用你對這些提示的回應,搭配 Bicep 設定檔來建立並設定這些必要的 Azure 資源:- 彈性使用量方案和函數應用程式
- Azure 儲存體(必需)與 Application Insights(推薦)
- 耐用任務排程器與任務中心
- 您帳戶的存取原則和角色
- 使用受管理的身份識別(而非儲存的連接字串)的服務對服務連線
命令成功完成之後,您會看到所建立資源的連結。
佈建也會執行佈建後指令碼,在您的應用程式資料夾中產生 local.settings.json 檔案。 這個檔案包含已部署的 Durable Task Scheduler 端點的連線設定,你需要它來本地執行專案。
啟動 Azurite
要在本地執行專案,Functions 執行環境需要本地儲存模擬器。
"AzureWebJobsStorage": "UseDevelopmentStorage=true"local.settings.json 檔案中的設定指示執行時使用 Azurite 來達成此目的。
在新的終端機視窗中,執行以下指令啟動 Azurite:
azurite --skipApiVersionCheck --location ~/azurite-data
在本地測試時,請讓 Azurite 持續在這個終端視窗中運行。
在您的本機環境中執行
在你原本的終端機裡,進入
fanoutfanin應用程式資料夾並啟動 Functions 主機:cd fanoutfanin func start當 Functions 主機在你本地專案資料夾啟動時,它會把 HTTP 觸發函式的本地 URL 端點寫入終端機輸出。
Note
因為本地執行時不會強制執行存取金鑰授權,所以呼叫函式不需要存取金鑰。
在瀏覽器中,向啟動編排的端點發出 GET 請求:
http://localhost:7071/api/FetchOrchestration_HttpStart
此請求啟動一個新的編排實例。 此編排流程會展開為多個活動,以並行取得 Microsoft Learn 文章的標題。 當活動結束後,編排磁區會重新進入,並將標題作為格式化字串傳回。
在你原本的終端機裡,進入
src應用程式資料夾,建立並啟用虛擬環境,安裝相依關係,然後啟動 Functions 主機:cd src你建立並啟用虛擬環境(稱為
.venv)的方式取決於你的終端機:python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt func start當 Functions 主機在你本地專案資料夾啟動時,它會把 HTTP 觸發函式的本地 URL 端點寫入終端機輸出。
Note
因為本地執行時不會強制執行存取金鑰授權,所以呼叫函式不需要存取金鑰。
在你的瀏覽器中,對 HTTP 開始端點發出 GET 請求:
http://localhost:7071/api/orchestrators/fetch_orchestration
此請求啟動一個新的編排實例。 此編排流程會展開為多個活動,以並行取得 Microsoft Learn 文章的標題。 當活動結束後,編排磁區會重新進入,並將標題作為格式化字串傳回。
在你原本的終端機裡,進入
src應用程式資料夾,安裝相依,建立專案,然後啟動 Functions 主機:cd src npm install npm run build func start當 Functions 主機在你本地專案資料夾啟動時,它會把 HTTP 觸發函式的本地 URL 端點寫入終端機輸出。
Note
因為本地執行時不會強制執行存取金鑰授權,所以呼叫函式不需要存取金鑰。
在你的瀏覽器中,對 HTTP 開始端點發出 GET 請求:
http://localhost:7071/api/orchestrators/fetchOrchestration
此請求啟動一個新的編排實例。 此編排流程會展開為多個活動,以並行取得 Microsoft Learn 文章的標題。 當活動結束後,編排磁區會重新進入,並將標題作為格式化字串傳回。
在你原本的終端機裡,建立專案,然後從建構輸出資料夾啟動 Functions 主機:
mvn clean package cd target/azure-functions/durable-functions-quickstart func start當 Functions 主機在你本地專案資料夾啟動時,它會把 HTTP 觸發函式的本地 URL 端點寫入終端機輸出。
Note
因為本地執行時不會強制執行存取金鑰授權,所以呼叫函式不需要存取金鑰。
在瀏覽器中,向啟動編排的端點發出 GET 請求:
http://localhost:7071/api/FetchOrchestration_HttpStart
此請求啟動一個新的編排實例。 此編排流程會展開為多個活動,以並行取得 Microsoft Learn 文章的標題。 當活動結束後,編排磁區會重新進入,並將標題作為格式化字串傳回。
在原本的終端機中,前往
src應用程式資料夾,安裝相依性,然後啟動 Functions 主機:cd src npm install func start當 Functions 主機在你本地專案資料夾啟動時,它會把 HTTP 觸發函式的本地 URL 端點寫入終端機輸出。
Note
因為本地執行時不會強制執行存取金鑰授權,所以呼叫函式不需要存取金鑰。
在瀏覽器中,向啟動編排的端點發出 GET 請求:
http://localhost:7071/api/FetchOrchestration_HttpStart
此請求啟動一個新的編排實例。 此編排流程會展開為多個活動,以並行取得 Microsoft Learn 文章的標題。 當活動結束後,編排磁區會重新進入,並將標題作為格式化字串傳回。
在你原本的終端機裡,進入
src應用程式資料夾並啟動 Functions 主機:cd src func start當 Functions 主機在你本地專案資料夾啟動時,它會把 HTTP 觸發函式的本地 URL 端點寫入終端機輸出。
Note
因為本地執行時不會強制執行存取金鑰授權,所以呼叫函式不需要存取金鑰。
在瀏覽器中,向啟動編排的端點發出 GET 請求:
http://localhost:7071/api/FetchOrchestration_HttpStart
此請求啟動一個新的編排實例。 此編排流程會展開為多個活動,以並行取得 Microsoft Learn 文章的標題。 當活動結束後,編排磁區會重新進入,並將標題作為格式化字串傳回。
HTTP 端點會回傳包含多個 URL 的 JSON 回應。
statusQueryGetUri端點會提供編排狀態。複製該
statusQueryGetUri值並貼到瀏覽器或 HTTP 測試工具中,以檢查編排狀態。 當協調完成後,你會在回應中看到擷取的文章標題。當您完成時,請在終端機視窗中按 Ctrl+C 以停止
func主機程序。
- 執行
deactivate以關閉虛擬環境。
檢閱程式碼 (選用)
你可以參考實作扇出/扇入模式的程式碼:
標題擷取活動會透過動態任務清單來追蹤。 線路 await Task.WhenAll(parallelTasks); 會等待所有同時執行的已呼叫活動完成。 完成後,所有輸出會以格式化字串形式彙總。
[Function(nameof(FetchOrchestration))]
public static async Task<string> RunOrchestrator(
[OrchestrationTrigger] TaskOrchestrationContext context)
{
ILogger logger = context.CreateReplaySafeLogger(nameof(FetchOrchestration));
logger.LogInformation("Fetching data.");
var parallelTasks = new List<Task<string>>();
// List of URLs to fetch titles from
var urls = new List<string>
{
"https://learn.microsoft.com/azure/azure-functions/durable/durable-functions-overview",
"https://learn.microsoft.com/azure/azure-functions/durable/durable-task-scheduler/durable-task-scheduler",
"https://learn.microsoft.com/azure/azure-functions/functions-scenarios",
"https://learn.microsoft.com/azure/azure-functions/functions-create-ai-enabled-apps",
};
// Run fetching tasks in parallel
foreach (var url in urls)
{
Task<string> task = context.CallActivityAsync<string>(nameof(FetchTitleAsync), url);
parallelTasks.Add(task);
}
// Wait for all the parallel tasks to complete before continuing
await Task.WhenAll(parallelTasks);
// Return fetched titles as a formatted string
return string.Join("; ", parallelTasks.Select(t => t.Result));
}
你可以查看完整的範本專案here。
標題擷取活動會透過動態任務清單來追蹤。 線路 yield context.task_all(tasks) 會等待所有同時執行的已呼叫活動完成。 完成後,所有輸出會以格式化字串形式彙總。
# List of URLs to fetch titles from
urls = [
"https://learn.microsoft.com/azure/azure-functions/durable/durable-functions-overview",
"https://learn.microsoft.com/azure/azure-functions/durable/durable-task-scheduler/durable-task-scheduler",
"https://learn.microsoft.com/azure/azure-functions/functions-scenarios",
"https://learn.microsoft.com/azure/azure-functions/functions-create-ai-enabled-apps",
]
# Run fetching tasks in parallel
tasks = []
for url in urls:
task = context.call_activity("fetch_title", url)
tasks.append(task)
# Wait for all the parallel tasks to complete before continuing
results = yield context.task_all(tasks)
# Return fetched titles as a formatted string
return "; ".join(results)
@myApp.activity_trigger(input_name="url")
async def fetch_title(url: str):
"""Activity function that fetches the title from a URL."""
logger = logging.getLogger("FetchTitle")
logger.info(f"Fetching from url {url}.")
try:
async with ClientSession() as session:
你可以查看完整的範本專案here。
標題擷取活動會透過動態任務清單來追蹤。 線路 yield context.df.Task.all(parallelTasks) 會等待所有同時執行的已呼叫活動完成。 完成後,所有輸出會以格式化字串形式彙總。
const urls = [
"https://learn.microsoft.com/azure/azure-functions/durable/durable-functions-overview",
"https://learn.microsoft.com/azure/azure-functions/durable/durable-task-scheduler/durable-task-scheduler",
"https://learn.microsoft.com/azure/azure-functions/functions-scenarios",
"https://learn.microsoft.com/azure/azure-functions/functions-create-ai-enabled-apps",
];
// Run fetching tasks in parallel
const parallelTasks = [];
for (const url of urls) {
const task = context.df.callActivity(fetchTitleActivityName, url);
parallelTasks.push(task);
}
// Wait for all the parallel tasks to complete before continuing
const results: string[] = yield context.df.Task.all(parallelTasks);
// Return fetched titles as a formatted string
return results.join("; ");
};
df.app.orchestration("fetchOrchestration", fetchOrchestration);
const fetchTitleAsync: ActivityHandler = async function (
url: string,
context: InvocationContext
你可以查看完整的範本專案here。
標題擷取活動會透過動態任務清單來追蹤。 線路 ctx.allOf(parallelTasks).await() 會等待所有同時執行的已呼叫活動完成。 完成後,所有輸出會以格式化字串形式彙總。
@FunctionName("FetchOrchestration")
public String runOrchestrator(
@DurableOrchestrationTrigger(name = "taskOrchestrationContext") TaskOrchestrationContext ctx) {
List<String> urls = List.of(
"https://learn.microsoft.com/azure/azure-functions/durable/durable-functions-overview",
"https://learn.microsoft.com/azure/azure-functions/durable/durable-task-scheduler/durable-task-scheduler",
"https://learn.microsoft.com/azure/azure-functions/functions-scenarios",
"https://learn.microsoft.com/azure/azure-functions/functions-create-ai-enabled-apps"
);
// Fan out: run fetching tasks in parallel
List<Task<String>> parallelTasks = urls.stream()
.map(url -> ctx.callActivity("FetchTitle", url, String.class))
.collect(Collectors.toList());
// Fan in: wait for all parallel tasks to complete
List<String> results = ctx.allOf(parallelTasks).await();
// Return fetched titles as a formatted string
return String.join("; ", results);
}
你可以查看完整的範本專案here。
標題擷取活動會透過動態任務清單來追蹤。 線路 yield context.df.Task.all(parallelTasks) 會等待所有同時執行的已呼叫活動完成。 完成後,所有輸出會以格式化字串形式彙總。
df.app.orchestration('fetchOrchestration', function* (context) {
context.log("Fetching data.");
const urls = [
"https://learn.microsoft.com/azure/azure-functions/durable/durable-functions-overview",
"https://learn.microsoft.com/azure/azure-functions/durable/durable-task-scheduler/durable-task-scheduler",
"https://learn.microsoft.com/azure/azure-functions/functions-scenarios",
"https://learn.microsoft.com/azure/azure-functions/functions-create-ai-enabled-apps",
];
// Fan out: run fetching tasks in parallel
const parallelTasks = urls.map(url => context.df.callActivity(activityName, url));
// Fan in: wait for all parallel tasks to complete
const results = yield context.df.Task.all(parallelTasks);
// Return fetched titles as a formatted string
return results.join("; ");
});
你可以查看完整的範本專案here。
標題擷取活動會透過動態任務清單來追蹤。 線路 Wait-ActivityFunction -Task $parallelTasks 會等待所有同時執行的已呼叫活動完成。 完成後,所有輸出會以格式化字串形式彙總。
param($Context)
$urls = @(
"https://learn.microsoft.com/azure/azure-functions/durable/durable-functions-overview",
"https://learn.microsoft.com/azure/azure-functions/durable/durable-task-scheduler/durable-task-scheduler",
"https://learn.microsoft.com/azure/azure-functions/functions-scenarios",
"https://learn.microsoft.com/azure/azure-functions/functions-create-ai-enabled-apps"
)
# Fan out: run fetching tasks in parallel
$parallelTasks = @()
foreach ($url in $urls) {
$parallelTasks += Invoke-DurableActivity -FunctionName 'FetchTitle' -Input $url -NoWait
}
# Fan in: wait for all parallel tasks to complete
$results = Wait-ActivityFunction -Task $parallelTasks
# Return fetched titles as a formatted string
$output = $results -join "; "
$output
你可以查看完整的範本專案here。
在本機驗證函式後,就可以將這些函式部署到 Azure。
部署至 Azure
從根專案資料夾執行這個指令,將你的程式碼專案部署到 Azure 的函式應用程式:
azd deploy
azd deploy 命令會將您的程式碼打包並部署到在佈建期間建立的函式應用程式。 指令完成後,應用程式會在已部署的套件中啟動並執行。
在 Azure 上調用函數
你現在可以在 Azure 中透過對其 URL 發出 HTTP 請求來調用你的協調端點。 當你的函式在 Azure 執行時,存取金鑰授權會被強制執行,且你必須在請求時提供函式存取金鑰。
您可以使用 Core Tools 來取得啟動 Azure 中編排的 HTTP 觸發器的 URL 端點。
在您的本機終端機或命令提示字元中,執行這些命令以取得 URL 端點值:
APP_NAME=$(azd env get-value AZURE_FUNCTION_NAME) func azure functionapp list-functions $APP_NAME --show-keysazd env get-value命令會從本機環境取得函數應用程式名稱。 當你將--show-keys選項與func azure functionapp list-functions一起使用時,每個端點的 Invoke URL 值中都會包含任何所需的函式層級存取鍵。使用瀏覽器或 HTTP 測試工具,向 HTTP start 端點發出 GET 請求,啟動你在 Azure 運行的函式應用程式中的協調。
重新部署你的程式碼
視需要多次執行 azd deploy,以將程式碼更新部署至函式應用程式。 如果你需要更新 Azure 資源,請重新執行azd provision。
Note
最新的部署套件總是會覆寫已部署的程式碼檔案。
您對 azd 提示的初始回應,以及由 azd 產生的任何環境變數,都會儲存在您命名的環境中。 使用 azd env get-values 指令來檢視你在建立 Azure 資源時使用的所有變數。
清理資源
當你完成函式應用程式及相關資源的運作後,請使用此指令從 Azure 刪除函式應用程式及其相關資源,避免產生任何額外費用:
azd down --no-prompt
Note
--no-prompt 選項會指示 azd 刪除您的資源群組,而不需要您確認。
此命令不會影響您的本機程式碼專案。