Durable Functions för tillståndsbevarande arbetsflöden
Orkestrera långvariga arbetsflöden med orkestreringsmönster i Durable Functions (fan-out/fan-in, kedjning, övervakning) och förstå hur tillstånd sparas som kontrollpunkter.
Durable Functions för tillståndsbevarande arbetsflöden är en gratis lektion i Azure Fundamentals på CoddyKit. Detta är lektion 2 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Azure Fundamentals, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Azure Fundamentals innehåller totalt 4 lektioner.
Varför Durable Functions?
Vanliga Azure Functions är tillståndslösa – varje anrop körs oberoende och har inget minne av tidigare anrop. Durable Functions utökar Azure Functions med möjligheten att skriva tillståndsbaserade arbetsflöden som körs länge med vanlig async/await-kod. Durable Task Framework sparar automatiskt kontrollpunkter för tillståndet i Azure Storage efter varje steg, så att arbetsflöden kan överleva serveromstarter, tidsgränser eller planerat underhåll och återupptas exakt där de avbröts.
De tre funktionstyperna
Durable Functions introducerar tre funktionstyper. En orkestreringsfunktion samordnar hela arbetsflödet – den anropar aktivitetsfunktioner och väntar på resultat med yield eller await utan att faktiskt blockera en tråd. En aktivitetsfunktion utför en enskild arbetsuppgift (anropar ett API eller skriver till en databas) och är den enda plats där sidoeffekter bör förekomma. En entitetsfunktion hanterar mindre delar av beständigt tillstånd (räknare och flaggor) mellan anrop.
// Client function (HTTP trigger) — starts the orchestration
module.exports = async function (context, req) {
const client = df.getClient(context);
const orderId = req.body.orderId;
const instanceId = await client.startNew('OrderOrchestrator', undefined, { orderId });
return client.createCheckStatusResponse(context.bindingData.req, instanceId);
};Kedjemönstret
Kedjemönstret kör aktivitetsfunktioner sekventiellt och skickar resultatet från en funktion som indata till nästa. Orkestreringsfunktionen väntar på varje aktivitet i tur och ordning. Om någon aktivitet misslyckas stoppas arbetsflödet och kan startas om från det steg som misslyckades. Detta är det enklaste Durable Functions-mönstret och passar arbetsflöden där varje steg är beroende av resultatet från föregående steg, till exempel bearbetningsflöden för beställningar.
// Orchestrator: chaining pattern
const df = require('durable-functions');
module.exports = df.orchestrator(function* (context) {
const orderId = context.df.getInput().orderId;
const validated = yield context.df.callActivity('ValidateOrder', orderId);
const charged = yield context.df.callActivity('ChargePayment', validated);
const shipped = yield context.df.callActivity('ShipOrder', charged);
return { status: 'shipped', trackingId: shipped.trackingId };
});Fan-out-/fan-in-mönstret
Fan-out-/fan-in-mönstret startar flera aktivitetsfunktioner parallellt och väntar på att alla ska slutföras innan körningen fortsätter. Orkestreringsfunktionen startar alla uppgifter samtidigt med callActivity utan att vänta på dem, samlar uppgiftsobjekten i en array och väntar sedan på Task.all(). Detta är mycket snabbare än sekventiell bearbetning för oberoende arbetsobjekt, till exempel bearbetning av flera filer, anrop till flera API:er eller batchåtgärder.
// Orchestrator: fan-out / fan-in
module.exports = df.orchestrator(function* (context) {
const items = context.df.getInput().items;
// Fan-out: start all tasks in parallel
const tasks = items.map(item => context.df.callActivity('ProcessItem', item));
// Fan-in: wait for all tasks to complete
const results = yield context.df.Task.all(tasks);
return results;
});Övervakningsmönstret
Övervakningsmönstret frågar regelbundet ett externt system tills ett villkor är uppfyllt – ungefär som en avfrågningsslinga, men helt beständigt. Orkestreringsfunktionen anropar en aktivitet för att kontrollera statusen, väntar ett konfigurerbart intervall med createTimer och upprepar sedan detta. Eftersom tillståndet sparas i lagring mellan varje avfrågning förbrukar orkestreringsfunktionen inga beräkningsresurser medan den väntar. Därför är mönstret mycket effektivare än en metod som använder en sovande timer.
// Orchestrator: monitor pattern (poll until job completes)
module.exports = df.orchestrator(function* (context) {
const jobId = context.df.getInput().jobId;
const expiry = new Date(context.df.currentUtcDateTime);
expiry.setHours(expiry.getHours() + 24); // 24-hour timeout
while (context.df.currentUtcDateTime < expiry) {
const status = yield context.df.callActivity('GetJobStatus', jobId);
if (status === 'completed') return { jobId, status };
if (status === 'failed') throw new Error('Job failed');
// Wait 30 seconds before next poll
const nextCheck = new Date(context.df.currentUtcDateTime);
nextCheck.setSeconds(nextCheck.getSeconds() + 30);
yield context.df.createTimer(nextCheck);
}
throw new Error('Workflow timed out');
});Mönstret för mänsklig interaktion
Mönstret för mänsklig interaktion pausar en orkestrering och väntar på en extern händelse, till exempel ett godkännande från en chef. Orkestreringsfunktionen väntar med waitForExternalEvent, vilket kan pågå i dagar eller veckor utan att förbruka beräkningsresurser. Ett externt system (en länk för godkännande via e-post, en mobilapp eller en webhook) anropar Durable Functions HTTP API för att utlösa händelsen och låsa upp orkestreringen. Kombinera detta med en timer för automatisk tidsgräns och eskalering om inget svar kommer.
// Orchestrator: wait for human approval with timeout
module.exports = df.orchestrator(function* (context) {
const request = context.df.getInput();
yield context.df.callActivity('SendApprovalEmail', request);
const timeout = df.Task.createTimer(context, new Date(Date.now() + 48 * 3600 * 1000));
const approval = context.df.waitForExternalEvent('ApprovalResponse');
const winner = yield context.df.Task.any([approval, timeout]);
if (winner === approval) {
const approved = winner.result;
return approved ? 'Approved' : 'Rejected';
} else {
return 'Timed out — escalated';
}
});Begränsningar för orkestreringsfunktioner
Orkestreringsfunktioner har viktiga begränsningar eftersom de kan spelas upp igen flera gånger från historiken för att återskapa tillståndet. De måste vara deterministiska – använd aldrig Date.now() eller Math.random(), och gör inga direkta I/O-anrop. Använd i stället context.df.currentUtcDateTime för tidsstämplar och anropa aktivitetsfunktioner för all I/O. Loggning i orkestreringsfunktionens kod ger dubbla loggposter vid uppspelning. Använd därför aktivitetsfunktioner för loggning i stället.
// WRONG — non-deterministic, will cause replay bugs
module.exports = df.orchestrator(function* (context) {
const now = new Date(); // Don't use Date()
const rand = Math.random(); // Don't use Math.random()
const data = await fetch('/api'); // Don't make HTTP calls directly
});
// CORRECT
module.exports = df.orchestrator(function* (context) {
const now = context.df.currentUtcDateTime; // OK
const data = yield context.df.callActivity('FetchData', null); // OK
});Hantera instanser: status och avslutning
Varje orkestreringskörning har ett unikt instans-ID som ni kan använda för att fråga efter status, skicka händelser eller avsluta körningen. Durable Functions HTTP-hanterings-API innehåller slutpunkter för att kontrollera status (GET /instances/{id}), skicka händelser (POST /instances/{id}/raiseEvent/{name}) och avsluta körningen (POST /instances/{id}/terminate). Använd Durable-klientbindningen i era funktioner för att komma åt dessa åtgärder programmatiskt.
// Client function: check orchestration status
module.exports = async function (context, req) {
const client = df.getClient(context);
const instanceId = req.params.instanceId;
const status = await client.getStatus(instanceId, true, true, true);
return {
status: 200,
body: {
instanceId,
runtimeStatus: status.runtimeStatus,
customStatus: status.customStatus,
output: status.output
}
};
};Lagringsbackend och prestanda
Durable Functions lagrar orkestreringshistorik, instanstillstånd och meddelandeköer mellan funktioner i ett Azure Storage Account (eller Azure SQL-/Netherite-backend för högre genomströmning). Varje kontrollpunkt skrivs till Azure Table Storage och Azure Queue Storage. I scenarier med hög genomströmning (tusentals samtidiga orkestreringar) använder Netherite-lagringsbackend Azure Event Hubs för mycket bättre prestanda. Övervaka orkestreringsköernas djup för att upptäcka flaskhalsar.
// host.json: configure the Durable Task storage provider
{
'version': '2.0',
'extensions': {
'durableTask': {
'hubName': 'MyTaskHub',
'storageProvider': {
'type': 'azure',
'connectionStringName': 'AzureWebJobsStorage',
'controlQueueBatchSize': 32,
'maxQueuePollingInterval': '00:00:02'
}
}
}
}Felhantering och omförsök
Aktivitetsfunktioner kan kasta undantag, som överförs tillbaka till orkestreringsfunktionen som TaskFailedException. Använd try-catch-block i orkestreringsfunktionen för att hantera fel på ett robust sätt. För övergående fel konfigurerar ni automatiska omförsök med gradvis längre väntetid genom callActivityWithRetry. Ange maximalt antal försök, det första omförsöksintervallet och en koefficient för ökningen. Detta är det rekommenderade mönstret för aktiviteter som anropar externa API:er eller databaser.
// Orchestrator: retry an activity with exponential backoff
module.exports = df.orchestrator(function* (context) {
const retryOptions = new df.RetryOptions(
5000, // firstRetryIntervalInMilliseconds
3 // maxNumberOfAttempts
);
retryOptions.backoffCoefficient = 2; // 5s, 10s, 20s
try {
const result = yield context.df.callActivityWithRetry(
'CallExternalAPI',
retryOptions,
context.df.getInput()
);
return result;
} catch (e) {
yield context.df.callActivity('SendFailureAlert', e.message);
throw e;
}
});Durable Entities
Durable Entities (entitetsfunktioner) implementerar mindre delar av beständigt tillstånd som är åtkomliga via en identitet, ungefär som virtuella aktörer. En entitet har ett ID och ett tillstånd som finns kvar mellan anrop. Ni anropar åtgärder på en entitet från en orkestreringsfunktion eller klient, och entiteten bearbetar dem en i taget (seriellt). Vanliga användningsområden är räknare, tillståndsmaskiner för godkännanden, hastighetsbegränsare och kundvagnar – alla scenarier som kräver beständigt och uppdateringsbart tillstånd utan en databas.
// Counter entity function
const df = require('durable-functions');
module.exports = df.entity(function (context) {
let count = context.df.getState(() => 0);
const operation = context.df.operationName;
if (operation === 'add') count += context.df.getInput();
if (operation === 'reset') count = 0;
if (operation === 'get') context.df.return(count);
context.df.setState(count);
});
// From orchestrator, increment counter entity
// const entityId = new df.EntityId('Counter', 'myCounter');
// yield context.df.callEntity(entityId, 'add', 1);Snabbkontroll
Testa era kunskaper om koncepten i Microsoft Azure Fundamentals (AZ-900) från den här lektionen.
Sammanfattning av lektionen
I den här lektionen lärde ni er att Durable Functions möjliggör tillståndsbaserade arbetsflöden som körs länge genom att spara kontrollpunkter för orkestreringsfunktionens tillstånd i Azure Storage, att viktiga mönster är kedja, fan-out/fan-in, övervakning och mänsklig interaktion samt att orkestreringsfunktioner måste vara deterministiska – all I/O och alla icke-deterministiska anrop måste gå via aktivitetsfunktioner. Nästa steg är Azure Logic Apps.
Lär dig Azure Fundamentals med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 30
- Lektioner
- 120
Vanliga frågor
Är lektionen ”Durable Functions för tillståndsbevarande arbetsflöden” gratis?
Ja – hela texten till ”Durable Functions för tillståndsbevarande arbetsflöden” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Azure Fundamentals, kan Ni uppgradera till CoddyKit PRO. Kursen i Azure Fundamentals innehåller totalt 4 lektioner.
Vad lär jag mig i ”Durable Functions för tillståndsbevarande arbetsflöden”?
Orkestrera långvariga arbetsflöden med orkestreringsmönster i Durable Functions (fan-out/fan-in, kedjning, övervakning) och förstå hur tillstånd sparas som kontrollpunkter. Ni övar på Azure Fundamentals med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Azure Fundamentals?
Du behöver inga förkunskaper. Utbildningen i Azure Fundamentals på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 2 av 4.
Hur lång tid tar lektionen ”Durable Functions för tillståndsbevarande arbetsflöden”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Azure Fundamentals-lektionen?
Ja. Varje Azure Fundamentals-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Azure Functions-utlösare och bindningar
- Durable Functions för tillståndsbevarande arbetsflöden
- Azure Logic Apps
- Event Grid och händelsestyrd arkitektur