Azure Fundamentals · leksjon

Durable Functions for tilstandsbevisste arbeidsflyter

Orkestrer langvarige arbeidsflyter ved hjelp av orkestreringsmønstre i Durable Functions (fan-out/fan-in, chaining, monitor), og forstå hvordan tilstanden lagres som kontrollpunkter.

Leksjon 2 av 413 trinn

Durable Functions for tilstandsbevisste arbeidsflyter er en gratis leksjon i Azure Fundamentals på CoddyKit. Dette er leksjon 2 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Azure Fundamentals, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Azure Fundamentals inneholder totalt 4 leksjoner.

Hvorfor Durable Functions?

Vanlige Azure Functions er tilstandsløse — hver kjøring utføres uavhengig, uten minne om tidligere kall. Durable Functions utvider Azure Functions med muligheten til å skrive tilstandsfulle, langvarige arbeidsflyter ved hjelp av vanlig async/await-kode. Durable Task Framework lagrer automatisk kontrollpunkter for tilstanden i Azure Storage etter hvert trinn, slik at arbeidsflyter kan overleve serveromstarter, tidsavbrudd eller planlagt vedlikehold og fortsette nøyaktig der de ble avbrutt.

De tre funksjonstypene

Durable Functions introduserer tre funksjonstyper. En orchestrator-funksjon koordinerer hele arbeidsflyten — den kaller aktivitetsfunksjoner og venter på resultater ved hjelp av yield eller await, uten faktisk å blokkere en tråd. En aktivitetsfunksjon utfører én enkelt arbeidsenhet (kaller et API eller skriver til en database) og er det eneste stedet der sideeffekter skal forekomme. En entitetsfunksjon vedlikeholder små deler av varig tilstand (tellere og flagg) på tvers av kall.

// 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);
};

Kjedemønsteret

Kjedemønsteret kjører aktivitetsfunksjoner sekvensielt og sender resultatet fra én funksjon videre som inndata til den neste. Orchestrator-funksjonen venter på hver aktivitet etter tur. Hvis en aktivitet mislykkes, stopper arbeidsflyten og kan startes på nytt fra trinnet som mislyktes. Dette er det enkleste Durable Functions-mønsteret og passer for arbeidsflyter der hvert trinn avhenger av resultatet fra det forrige, for eksempel behandlingspipelines for bestillinger.

// 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ønsteret

Fan-out-/fan-in-mønsteret starter flere aktivitetsfunksjoner parallelt og venter på at alle skal bli ferdige før arbeidsflyten fortsetter. Orchestrator-funksjonen starter alle oppgavene samtidig ved hjelp av callActivity uten å vente på dem, samler oppgaveobjektene i en tabell og bruker deretter Task.all(). Dette er betydelig raskere enn sekvensiell behandling av uavhengige arbeidselementer, for eksempel behandling av flere filer, kall til flere API-er eller satsvise operasjoner.

// 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;
});

Monitoreringsmønsteret

Monitoreringsmønsteret spør et eksternt system med jevne mellomrom helt til en betingelse er oppfylt — omtrent som en polling-løkke, men fullstendig varig. Orchestrator-funksjonen kaller en aktivitet for å kontrollere statusen, venter et konfigurerbart intervall ved hjelp av createTimer og gjentar deretter løkken. Fordi tilstanden lagres i et kontrollpunkt i lagringen mellom hver spørring, bruker orchestrator-funksjonen ingen beregningsressurser mens den venter. Dette gjør løsningen langt mer effektiv enn en tilnærming basert på et sovende tidsur.

// 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ønsteret for menneskelig interaksjon

Mønsteret for menneskelig interaksjon setter en orkestrering på pause og venter på en ekstern hendelse — for eksempel en godkjenning fra en leder. Orchestrator-funksjonen bruker waitForExternalEvent, som kan vente i flere dager eller uker uten å bruke beregningsressurser. Et eksternt system (en godkjenningslenke i en e-post, en mobilapp eller en webhook) kaller Durable Functions HTTP-API-et for å utløse hendelsen og oppheve blokkeringen av orkestreringen. Kombiner dette med et tidsur for automatisk tidsavbrudd og eskalering hvis det ikke kommer noe svar.

// 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';
  }
});

Begrensninger for orchestrator-funksjoner

Orchestrator-funksjoner har viktige begrensninger fordi de kan bli avspilt flere ganger fra historikken for å gjenoppbygge tilstanden. De må være deterministiske — bruk aldri Date.now() eller Math.random(), og utfør aldri direkte I/O-kall. Bruk i stedet context.df.currentUtcDateTime for tidsstempler, og kall aktivitetsfunksjoner for all I/O. Logging i selve orchestrator-koden vil føre til dupliserte loggoppføringer under avspilling. Bruk aktivitetsfunksjoner til logging i stedet.

// 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
});

Administrere instanser: status og avslutning

Hver orkestreringskjøring har en unik instans-ID som De kan bruke til å hente status, sende hendelser eller avslutte kjøringen. Durable Functions HTTP-administrasjons-API-et tilbyr endepunkter for å kontrollere status (GET /instances/{id}), sende hendelser (POST /instances/{id}/raiseEvent/{name}) og avslutte kjøringen (POST /instances/{id}/terminate). Bruk Durable-klientbindingen i funksjonene Deres for å få programmatisk tilgang til disse operasjonene.

// 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 og ytelse

Durable Functions lagrer orkestreringshistorikk, instanstilstand og meldingskøer mellom funksjoner i en Azure Storage-konto (eller i Azure SQL-/Netherite-backendløsninger for høyere gjennomstrømming). Hvert kontrollpunkt skriver til Azure Table Storage og Azure Queue Storage. I scenarier med høy gjennomstrømming (tusenvis av samtidige orkestreringer) bruker Netherite-lagringsbackend Azure Event Hubs for betydelig bedre ytelse. Overvåk dybden på orkestreringskøen for å oppdage flaskehalser.

// 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'
      }
    }
  }
}

Feilhåndtering og nye forsøk

Aktivitetsfunksjoner kan utløse unntak som sendes tilbake til orchestrator-funksjonen som TaskFailedException. Bruk try-catch-blokker i orchestrator-funksjonen for å håndtere feil på en kontrollert måte. For midlertidige feil kan De konfigurere automatiske nye forsøk med gradvis lengre intervaller ved hjelp av callActivityWithRetry. Angi maksimalt antall forsøk, det første intervallet mellom forsøkene og koeffisienten for gradvis økning. Dette er det anbefalte mønsteret for aktiviteter som kaller eksterne 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 (entitetsfunksjoner) implementerer små deler av varig tilstand som er tilgjengelig via en identitet — omtrent som virtuelle aktører. En entitet har en ID og en tilstand som bevares mellom kall. De kan kalle operasjoner på en entitet fra en orchestrator-funksjon eller klient, og entiteten behandler dem én om gangen (serialisert). Vanlige bruksområder er tellere, tilstandsmaskiner for godkjenning, hastighetsbegrensere og handlekurver — alle scenarier som trenger varig, oppdaterbar tilstand uten en database.

// 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);

Hurtigsjekk

Test forståelsen Deres av konseptene i Microsoft Azure Fundamentals (AZ-900) fra denne leksjonen.

Oppsummering av leksjonen

I denne leksjonen lærte De at Durable Functions muliggjør tilstandsfulle, langvarige arbeidsflyter ved å lagre kontrollpunkter for orchestrator-tilstanden i Azure Storage, at sentrale mønstre omfatter kjeding, fan-out/fan-in, monitorering og menneskelig interaksjon, og at orchestrator-funksjoner må være deterministiske — all I/O og alle ikke-deterministiske kall må gå gjennom aktivitetsfunksjoner. Neste tema er Azure Logic Apps.

Gratis å komme i gang

Lær deg Azure Fundamentals med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
30
Leksjoner
120

Ofte stilte spørsmål

Er leksjonen «Durable Functions for tilstandsbevisste arbeidsflyter» gratis?

Ja – hele teksten i «Durable Functions for tilstandsbevisste arbeidsflyter» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av Azure Fundamentals-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Azure Fundamentals inneholder totalt 4 leksjoner.

Hva lærer jeg i «Durable Functions for tilstandsbevisste arbeidsflyter»?

Orkestrer langvarige arbeidsflyter ved hjelp av orkestreringsmønstre i Durable Functions (fan-out/fan-in, chaining, monitor), og forstå hvordan tilstanden lagres som kontrollpunkter. Du øver på Azure Fundamentals med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med Azure Fundamentals?

Ingen tidligere erfaring er nødvendig. Azure Fundamentals på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 2 av 4.

Hvor lang tid tar leksjonen «Durable Functions for tilstandsbevisste arbeidsflyter»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne Azure Fundamentals-leksjonen?

Ja. Alle Azure Fundamentals-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Azure Functions-utløsere og bindinger
  2. Durable Functions for tilstandsbevisste arbeidsflyter
  3. Azure Logic Apps
  4. Event Grid og hendelsesdrevet arkitektur
← Tilbake til Azure Fundamentals