Durable Functions tilallisiin työnkulkuihin
Orkestroikaa pitkäkestoisia työnkulkuja Durable Functions -orkestrointimalleilla (fan-out/fan-in, ketjutus, valvonta) ja perehtykää tilan tarkistuspisteiden tallentamiseen.
Durable Functions tilallisiin työnkulkuihin on ilmainen Azure Fundamentals-oppitunti CoddyKitissä. Tämä on oppitunti 2/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Azure Fundamentals-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Azure Fundamentals-kurssilla on yhteensä 4 oppituntia.
Miksi Durable Functions?
Tavalliset Azure Functions -funktiot ovat tilattomia — jokainen kutsu suoritetaan itsenäisesti, eikä sillä ole tietoa aiemmista kutsuista. Durable Functions laajentaa Azure Functions -toimintoja mahdollistamalla tilallisten, pitkäkestoisten työnkulkujen kirjoittamisen tavallisella async/await-koodilla. Durable Task Framework tallentaa tilan automaattisesti tarkistuspisteenä Azure Storageen jokaisen vaiheen jälkeen, joten työnkulut kestävät palvelinten uudelleenkäynnistykset, aikakatkaisut ja suunnitellut huoltokatkot ja voivat jatkaa täsmälleen siitä kohdasta, johon ne jäivät.
Kolme funktiotyyppiä
Durable Functions sisältää kolme funktiotyyppiä. Orkestrointifunktio koordinoi koko työnkulkua — se kutsuu aktiviteettifunktioita ja odottaa tuloksia yield- tai await-avainsanan avulla estämättä kuitenkaan säiettä. Aktiviteettifunktio suorittaa yhden työyksikön (kutsuu APIa tai kirjoittaa tietokantaan), ja sen pitäisi olla ainoa paikka, jossa sivuvaikutuksia tapahtuu. Entiteettifunktio ylläpitää pieniä, säilyviä tilatietoja (laskureita ja lippuja) kutsujen välillä.
// 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);
};Ketjutusmalli
Ketjutusmallissa aktiviteettifunktiot suoritetaan peräkkäin siten, että yhden tuloste välitetään seuraavan syötteeksi. Orkestrointi odottaa jokaista aktiviteettia vuorollaan. Jos jokin aktiviteetti epäonnistuu, työnkulku pysähtyy ja se voidaan käynnistää uudelleen epäonnistuneesta vaiheesta. Tämä on Durable Functions -toimintojen yksinkertaisin malli, ja se sopii työnkulkuihin, joissa jokainen vaihe riippuu edellisen vaiheen tuloksesta, kuten tilausten käsittelyputkiin.
// 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- ja fan-in-malli
Fan-out- ja fan-in-mallissa käynnistetään useita aktiviteettifunktioita rinnakkain ja odotetaan niiden kaikkien valmistumista ennen jatkamista. Orkestrointi käynnistää kaikki tehtävät samanaikaisesti käyttämällä callActivity-kutsua ilman odottamista, kerää tehtäväoliot taulukkoon ja suorittaa sitten odotuksen kohteella Task.all(). Tämä on huomattavasti nopeampaa kuin peräkkäinen käsittely toisistaan riippumattomille työyksiköille, kuten useiden tiedostojen käsittelylle, useiden APIen kutsumiselle tai eräajoille.
// 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;
});Monitorointimalli
Monitorointimalli kyselyttää ulkoista järjestelmää tietyin väliajoin, kunnes ehto täyttyy — samoin kuin kyselysilmukka, mutta täysin säilyvänä. Orkestrointi kutsuu aktiviteettia tarkistamaan tilan, odottaa määritettävän ajan käyttäen createTimer-kutsua ja toistaa sitten silmukan. Koska tila tallennetaan tarkistuspisteenä tallennustilaan jokaisen kyselyn välillä, orkestrointi ei kuluta laskentaresursseja odottaessaan. Siksi tämä on paljon tehokkaampi kuin nukkumiseen perustuva ajastinratkaisu.
// 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');
});Ihmisen osallistumisen malli
Ihmisen osallistumisen malli keskeyttää orkestroinnin ja odottaa ulkoista tapahtumaa, kuten esihenkilön hyväksyntää. Orkestrointi odottaa kohteella waitForExternalEvent, joka voi odottaa päiviä tai viikkoja kuluttamatta laskentaresursseja. Ulkoinen järjestelmä (hyväksyntälinkki sähköpostissa, mobiilisovellus tai webhook) kutsuu Durable Functions -toimintojen HTTP-APIa tapahtuman välittämiseksi ja vapauttaa näin orkestroinnin jatkamaan. Yhdistämällä tämän ajastimeen voitte toteuttaa automaattisen aikakatkaisun ja eskaloinnin, jos vastausta ei saavu.
// 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';
}
});Orkestroinnin rajoitukset
Orkestrointifunktioihin liittyy tärkeitä rajoituksia, koska niitä voidaan suorittaa historiatietojen perusteella uudelleen useita kertoja tilan palauttamiseksi. Niiden on oltava deterministisiä — älkää koskaan käyttäkö Date.now()- tai Math.random()-kutsuja älkääkä tehkö suoria I/O-kutsuja. Käyttäkää aikaleimoihin sen sijaan context.df.currentUtcDateTime-arvoa ja tehkää kaikki I/O aktiviteettifunktioiden kautta. Orkestroinnin rungossa tehtävä lokikirjaus tuottaa toistettuja lokimerkintöjä uudelleensuorituksen aikana; käyttäkää lokikirjaukseen sen sijaan aktiviteettifunktioita.
// 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
});Instanssien hallinta: tila ja lopettaminen
Jokaisella orkestrointisuorituksella on yksilöllinen instanssitunnus, jonka avulla voitte kysellä sen tilaa, lähettää tapahtumia tai lopettaa sen. Durable Functions -toimintojen HTTP-hallinta-API tarjoaa päätepisteet tilan tarkistamiseen (GET /instances/{id}), tapahtumien lähettämiseen (POST /instances/{id}/raiseEvent/{name}) ja lopettamiseen (POST /instances/{id}/terminate). Käyttäkää funktioissanne Durable-asiakassidontaa näiden toimintojen ohjelmalliseen käyttöön.
// 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
}
};
};Tallennuksen taustajärjestelmä ja suorituskyky
Durable Functions tallentaa orkestrointihistorian, instanssien tilan ja funktioiden väliset viestijonot Azure Storage -tilille (tai Azure SQL- ja Netherite-taustajärjestelmiin suurempaa suorituskykyä varten). Jokainen tarkistuspiste kirjoitetaan Azure Table Storageen ja Azure Queue Storageen. Suuren suorituskyvyn tilanteissa (tuhansia samanaikaisia orkestrointeja) Netherite-tallennuksen taustajärjestelmä käyttää Azure Event Hubsia huomattavasti paremman suorituskyvyn saavuttamiseksi. Seuratkaa orkestrointijonon pituutta pullonkaulojen havaitsemiseksi.
// 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'
}
}
}
}Virheenkäsittely ja uudelleenyritykset
Aktiviteettifunktiot voivat heittää poikkeuksia, jotka välittyvät takaisin orkestroinnille TaskFailedException-poikkeuksina. Käsitelkää virheet hallitusti orkestroinnin try-catch-lohkoissa. Määrittäkää tilapäisiä virheitä varten automaattiset uudelleenyritykset viiveellä käyttäen callActivityWithRetry-kutsua ja määrittämällä yritysten enimmäismäärä, ensimmäisen uudelleenyrityksen väli sekä viiveen kasvukerroin. Tämä on suositeltu malli aktiviteeteille, jotka kutsuvat ulkoisia API-rajapintoja tai tietokantoja.
// 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-entiteetit
Durable-entiteetit (entiteettifunktiot) toteuttavat tunnisteen perusteella käytettäviä pieniä säilyviä tilatietoja — samankaltaisesti kuin virtuaaliset näyttelijät. Entiteetillä on tunnus ja tila, joka säilyy kutsujen välillä. Orkestrointi tai asiakas kutsuu entiteetin toimintoja, ja entiteetti käsittelee ne yksi kerrallaan (sarjoitettuna). Tavallisia käyttökohteita ovat laskurit, hyväksynnän tilakoneet, nopeusrajoittimet ja ostoskorit — kaikki tilanteet, joissa tarvitaan säilyvää ja päivitettävää tilaa ilman tietokantaa.
// 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);Pikatarkistus
Testatkaa, kuinka hyvin ymmärrätte tällä oppitunnilla käsitellyt Microsoft Azure Fundamentals (AZ-900) -käsitteet.
Oppitunnin kertaus
Tällä oppitunnilla opitte, että Durable Functions mahdollistaa tilalliset, pitkäkestoiset työnkulut tallentamalla orkestroinnin tilan tarkistuspisteinä Azure Storageen, keskeisiä malleja ovat ketjutus, fan-out ja fan-in, monitorointi sekä ihmisen osallistuminen ja orkestrointien on oltava deterministisiä — kaikki I/O-toiminnot ja ei-deterministiset kutsut on tehtävä aktiviteettifunktioiden kautta. Seuraavaksi tutustumme Azure Logic Apps -palveluun.
Opi Azure Fundamentals tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 30
- Oppitunnit
- 120
Usein kysytyt kysymykset
Onko oppitunti ”Durable Functions tilallisiin työnkulkuihin” ilmainen?
Kyllä – oppitunnin ”Durable Functions tilallisiin työnkulkuihin” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Azure Fundamentals-kurssin, päivitä CoddyKit PROhon. Azure Fundamentals-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Durable Functions tilallisiin työnkulkuihin”?
Orkestroikaa pitkäkestoisia työnkulkuja Durable Functions -orkestrointimalleilla (fan-out/fan-in, ketjutus, valvonta) ja perehtykää tilan tarkistuspisteiden tallentamiseen. Harjoittelet Azure Fundamentals-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Azure Fundamentals-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Azure Fundamentals-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/4.
Kuinka kauan ”Durable Functions tilallisiin työnkulkuihin”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Azure Fundamentals-oppitunnilla?
Kyllä. Jokainen Azure Fundamentals-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- Azure Functions -laukaisimet ja sidonnat
- Durable Functions tilallisiin työnkulkuihin
- Azure Logic Apps
- Event Grid ja tapahtumapohjainen arkkitehtuuri