Langer Workflow benötigt? Durable Function erstellen
CloudTrips benötigt einen Workflow, der Arbeit ausführen, warten und fortfahren kann, ohne eine einzelne Funktionsausführung aktiv zu halten. Durable Functions erweitert Azure Functions um gespeicherten Workflowzustand, Checkpoints, Wiederholungen und Wiederherstellung.
HTTP starter → startet und liefert eine Instanz-ID
Orchestrator → definiert die Workflow-Reihenfolge
Activity → führt eine echte Arbeitseinheit aus
Durable timer → speichert die Wartezeit, ohne einen Worker zu belegen
Eine gewöhnliche Funktion sollte eine Ausführung schnell beenden. Eine Durable Orchestration kann Minuten, Tage oder länger warten, weil Azure ihren Verlauf in Storage speichert und den Zustand beim Fortsetzen rekonstruiert.
Erstelle die Function App
Suche nach Function App, wähle Create, dann Flex Consumption und Select. Trage ein:
Subscription: CloudTrips TEST
Resource group: rg-cloudtrips-durable-test-weu
Function App name: func-cloudtrips-durable-dmytro-test-weu
Region: West Europe
Runtime stack: Node.js
Version: 22 LTS
Instance size: 2048 MB
Verwende die neueste angebotene Node.js-LTS-Version, falls 22 LTS nicht mehr
aufgeführt ist. Erstelle unter Storage das standardmäßige
Host-Storage-Konto. Durable Functions verwendet Storage, um
Orchestrierungsinstanzen, Verlauf, Nachrichten und Timer dauerhaft zu speichern.
Lasse Application Insights unter Monitoring aktiviert. Wähle unter Authentication Managed identity for all resources. Übernimm die übrigen Standardwerte und wähle Review + create > Create.
Der App-Name muss global eindeutig sein. Flex Consumption skaliert auf null, Storage und Application Insights können jedoch geringe Kosten verursachen.

Erteile die Durable-Storage-Rollen
Managed Identity vermeidet einen Storage-Schlüssel, die Identität benötigt jedoch weiterhin Datenzugriff, um den Durable Task Hub zu erstellen und zu verwenden. Öffne in der Function App Settings > Identity, wähle User assigned und notiere die für die App ausgewählte verwaltete Identität.
Öffne das Host-Storage-Konto der Function App, wähle Access control (IAM) und weise dieser verwalteten Identität alle drei Rollen zu:
Storage Blob Data Contributor
Storage Queue Data Contributor
Storage Table Data Contributor
Durable Functions verwendet Blobs für Leases und große Nachrichten, Queues zur Planung von Orchestrator- und Activity-Arbeit und Tabellen für Instanzzustand und Ausführungsverlauf. Owner oder Contributor auf Subscription-Ebene ist kein Ersatz: Diese Management-Plane-Rollen gewähren keinen Zugriff auf Storage-Daten.
Existiert eine Rolle bereits für die Identität, füge sie nicht doppelt hinzu. Warte vor dem ersten Orchestrierungsstart einige Minuten auf die RBAC-Übertragung.

Ohne die Tabellenrolle kann der HTTP-Starter beim Aufruf von
Table.CreateIfNotExistsAsync mit DurableTaskStorageException fehlschlagen.
Erstelle das lokale Projekt
Erstelle den Projektordner:
mkdir -p cloudtrips-durable/src/functions
cd cloudtrips-durable
Erstelle und validiere host.json:
cat > host.json <<'EOF'
{
"version": "2.0",
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[4.*, 5.0.0)"
}
}
EOF
jq . host.json
Das Extension Bundle liefert die Durable-Functions-Runtime-Bindings. jq muss
gültiges JSON ausgeben; stelle keine leere host.json bereit.
Erstelle package.json:
cat > package.json <<'EOF'
{
"name": "cloudtrips-durable",
"version": "1.0.0",
"main": "src/functions/*.js",
"scripts": {
"start": "func start"
},
"dependencies": {
"@azure/functions": "^4.7.2",
"durable-functions": "^3.3.0"
}
}
EOF
jq . package.json
Das Node.js-v4-Programmiermodell registriert Funktionen im Code. Das Paket
durable-functions 3.x ergänzt Orchestrator-, Activity- und Durable-Client-APIs.
Füge den Durable Workflow hinzu
Erstelle src/functions/tripWorkflow.js:
cat > src/functions/tripWorkflow.js <<'EOF'
const { app } = require('@azure/functions');
const df = require('durable-functions');
df.app.activity('recordTripStage', {
handler: (stage, context) => {
context.log(`Processing stage: ${stage}`);
return `${stage} completed`;
}
});
df.app.orchestration('tripOrchestrator', function* (context) {
const results = [];
results.push(
yield context.df.callActivity('recordTripStage', 'Reservation requested')
);
const resumeAt = new Date(context.df.currentUtcDateTime);
resumeAt.setMinutes(resumeAt.getMinutes() + 2);
yield context.df.createTimer(resumeAt);
results.push(
yield context.df.callActivity('recordTripStage', 'Reservation confirmed')
);
return results;
});
app.http('startTripWorkflow', {
methods: ['POST'],
authLevel: 'anonymous',
route: 'workflows/trips',
extraInputs: [df.input.durableClient()],
handler: async (request, context) => {
const client = df.getClient(context);
const instanceId = await client.startNew('tripOrchestrator');
context.log(`Started orchestration ${instanceId}`);
return client.createCheckStatusResponse(request, instanceId);
}
});
EOF
Der Orchestrator ist eine Generatorfunktion, weil Durable Functions an jeder
ausgegebenen Durable Task pausiert und den Workflowverlauf später wiedergeben
kann. Halte Orchestratorcode deterministisch: Verwende für
Workflowentscheidungen context.df.currentUtcDateTime statt new Date() und
führe Netzwerk-, Datenbank- oder Zufallsarbeit in Activities aus.
Der zweiminütige Durable Timer hält keinen Worker und berechnet nicht
durchgehend eine untätige Ausführung. Azure setzt einen Checkpoint, weckt die
Orchestrierung nach dem Timer und plant die zweite Aktivität. Zwei Minuten
lassen genügend Zeit, den Workflow im Zustand Running abzufragen.
Stelle den Workflow bereit
Paketisiere den Projektinhalt:
zip -r cloudtrips-durable.zip host.json package.json src
Stelle ihn mit einem Remote-Build der Abhängigkeiten bereit:
az functionapp deployment source config-zip \
--resource-group rg-cloudtrips-durable-test-weu \
--name func-cloudtrips-durable-dmytro-test-weu \
--src cloudtrips-durable.zip \
--build-remote true
Warte auf das Deployment-Ende und öffne Functions. Die Liste sollte zeigen:
startTripWorkflow
tripOrchestrator
recordTripStage

Starte eine Orchestrierung
Öffne startTripWorkflow, wähle Get Function URL und kopiere die URL. Starte
einen Workflow und speichere die Azure-Managementantwort:
curl --fail --show-error \
--request POST \
'<FUNCTION_URL>' \
| tee durable-start.json
Der HTTP-Starter antwortet mit 202 Accepted, einer eindeutigen id und
Management-URLs. Er hält die ursprüngliche HTTP-Anfrage nicht während des
gesamten Workflows offen.
Extrahiere die Status-URL:
jq -r '.statusQueryGetUri' durable-start.json
Kopiere die vollständige Ausgabe dieses Befehls. Die URL enthält Instanz-ID, Task-Hub-Angaben und den Autorisierungscode für den Management-Endpunkt.

Frage den gespeicherten Status ab
Rufe die zurückgegebene Status-URL auf:
curl --fail --show-error \
'<VOLLSTAENDIGE_statusQueryGetUri_HIER_EINFUEGEN>' \
| jq '{instanceId, runtimeStatus, output}'
Ersetze den gesamten Platzhalter einschließlich der spitzen Klammern durch die
vollständige aus statusQueryGetUri kopierte URL. Kürze die URL nicht und
entferne ihren Query-String nicht.
Während des Durable Timers sollte runtimeStatus den Wert Running haben und
output ist null. Wiederhole den Befehl nach etwa zwei Minuten. Erwartetes
Ergebnis:
{
"instanceId": "<unique-instance-id>",
"runtimeStatus": "Completed",
"output": [
"Reservation requested completed",
"Reservation confirmed completed"
]
}
Über die Instanz-ID korreliert Azure jeden Checkpoint und setzt auch nach einem Host-Neustart den richtigen Workflow fort. Öffne Monitor des Orchestrators, um die abgeschlossene Ausführung und Application-Insights-Telemetrie zu prüfen.

Bereinigen
Lösche die isolierte Ressourcengruppe:
az group delete \
--name rg-cloudtrips-durable-test-weu \
--yes
Bestätige die Löschung:
az group exists --name rg-cloudtrips-durable-test-weu
Erwartetes Ergebnis: false.