Háttérfeladatok futtatása webalkalmazásban: sorok, ütemezők és cron
Háttérfeladatok futtatásához először bontsd szét a munkát két fajtára. Az eseményindított feladatok (üdvözlő e-mail küldése, feltöltés feldolgozása) elmenthetők egy feladatsorba, ami gyakran egy tábla az adatbázisodban, és egy worker kezeli újrapróbálkozásokkal. Az ütemezett feladatok (éjszakai jelentés, emlékeztetők 15 percenként) olyasmit igényelnek, ami időzítetten indul: a tárhely cron funkcióját, vagy egy külső ütemezőt, amely az alkalmazásod egy védett végpontját hívja. Mindig tedd biztonságossá, hogy a feladatok kétszer is lefuthassanak, rögzítsd a hibákat, és soha ne támaszkodj időzítőre olyan szerveren, amely elalhat vagy újraindulhat.
Ez az útmutató bemutatja a lehetőségeket, azt, mikor melyik illik, és azt, hogyan állítsd be őket AI-alkalmazásépítővel, akár nullára skálázódó tárhelyen is.
Mi számít háttérfeladatnak?
Minden olyan, ami lassú, megbízhatatlan, vagy nem szükséges a felhasználó azonnali válaszához:
- E-mailek, értesítések és nyugták küldése
- Képek átméretezése, videók átkódolása, PDF-ek generálása
- Lassú harmadik féltől származó API-k hívása, beleértve a mesterséges intelligencia-modelleket hosszabb feladatokhoz
- Adatok importálása vagy szinkronizálása másik rendszerből
- Éjszakai takarítás, jelentések és emlékeztetők
Ha ezt a kérésen belül végzed, az oldalak lassúak és törékenyek lesznek: ha az e-mail-szolgáltató nem elérhető, a felhasználó regisztrációja meghiúsul. A háttérbe helyezés azt jelenti, hogy a felhasználó azonnali választ kap, a feladat pedig újrapróbálható.
A lehetőségek
| Lehetőség | Hogyan működik | Előnyök | Hátrányok |
|---|---|---|---|
| Tüzeld és felejtsd el ugyanabban a folyamatban | Válaszolj, majd a szerveren folytasd a munkát | Nincs beállítás | Elvész, ha a szerver leáll; nincs újrapróbálkozás |
Folyamaton belüli időzítő (setInterval, setTimeout) | Időzítő a futó szerverben | Triviális | Alvás közben nem fut; több példánynál duplikálódik |
| Adatbázis-alapú sor | A feladatok sorokként mentődnek; egy worker átveszi és futtatja | A meglévő adatbázist használja; tartós; könnyen ellenőrizhető | Az újrapróbálkozást és a zárolást neked kell megépíteni; kell valami, ami a workert futtatja |
| Dedikált sor (Redis-alapú vagy menedzselt) | Sorszolgáltatás plusz workerek | Kiforrott újrapróbálkozási és ütemezési funkciók | Újabb szolgáltatás, amit futtatni és fizetni kell |
| Hostolt feladat- vagy workflow-szolgáltatás | Harmadik fél hívja a végpontjaidat újrapróbálkozásokkal és ütemezéssel | Az ütemezést és az újrapróbálkozást kezeli helyetted | Szállítófüggőség; újabb fiók és kulcs |
| Külső ütemező, amely végpontot hív | Egy másik helyen lévő időzítő időzítetten HTTP-kérést küld | Bármely tárhelyen működik, a nullára skálázódókon is | Minimális időközök és késések; a végpontot védeni kell |
| A tárhely beépített cronja | A platform időzítetten futtat egy parancsot | Egyszerű, ahol elérhető | Nem minden tárhely kínálja |
Nincs egyetlen helyes válasz. Egy kis alkalmazásnak gyakran csak egy adatbázis-sor és egy külső ütemező kell.
Miért változtatja meg a képet a nullára skálázódó tárhely?
Sok modern tárhely elaltatja az alkalmazásodat, ha senki nem használja, és a következő kérésre felébreszti. Ez pénzt takarít meg, de egy alvó szerver nem futtat kódot: az időzítők nem indulnak el, a workerek nem kérdeznek le. Ezeken a tárhelyeken az ütemezett munkának bejövő kéréssel kell indulnia, és a legegyszerűbb forrás ehhez egy külső ütemező. Minden hívás felébreszti az alkalmazást (és gyakran az adatbázisát is), tehát a percenkénti hívás többe kerül, mint a 15 percenkénti. Válaszd azt a leglassúbb ütemezést, amely megfelel az igénynek.
1. minta: adatbázis-feladatsor
Az eseményindított feladatokhoz:
- Hozz létre egy
jobstáblát: típus, adattartalom (JSON), állapot (pending,running,done,failed), próbálkozások száma, run_after, last_error, időbélyegek. - Amikor valami történik, szúrj be egy feladat-sort ugyanabban a tranzakcióban, mint az azt kiváltó változtatás, így együtt sikerülnek vagy hibásodnak meg.
- Egy worker felveszi az esedékes feladatokat,
runningállapotra állítja, elvégzi a munkát, ésdoneállapotra állítja. - Hiba esetén növeld a
attemptsértékét, állíts be későbbirun_afteridőpontot (például 1, 5, majd 30 perc múlva), és mentsd a hibát. Maximum elérése után jelöldfailedállapotúra, és értesíts valakit.
Ha egyszerre több worker is futhat, a feladatokat biztonságosan kell átvenni. Postgresen a SELECT ... FOR UPDATE SKIP LOCKED lehetővé teszi, hogy minden worker más-más sorokat vegyen át, ütközés nélkül.
Mi futtatja a workert? Mindig futó szerveren egy külön folyamatban futó ciklus. Nullára skálázódó tárhelyen a 2. mintában leírt ütemezett végpont minden hívásnál feldolgozhat egy köteg esedékes feladatot.
2. minta: külső ütemező, amely az alkalmazásodat hívja
Az ütemezett feladatokhoz:
- Adj hozzá egy végpontot, például
POST /api/cron/send-reminders. - Védd: kérj titkos tokent egy fejlécben, tárold titokként mindkét oldalon, és utasíts el mindent más.
- Tedd idempotenssé: ha ugyanabban a percben kétszer fut, ne küldjön két emlékeztetőt. Rögzítsd, mi lett elküldve.
- Tartsd rövidre minden hívást: dolgozz fel egy köteget (mondjuk 100 elemet), a következő hívás vegye át a többit.
- Irányíts egy ütemezőt rá.
Ütemezőválasztások:
- GitHub Actions ütemezett workflow-k. Ingyenesek a GitHub használati korlátain belül. A GitHub dokumentációja szerint 2026 szeptemberétől a legrövidebb időköz 5 percenként egyszer, a futások terhelt időszakokban késhetnek (különösen minden óra elején), az ütemezések alapértelmezés szerint UTC-t használnak, és a nyilvános tárolóban lévő ütemezett workflow-k 60 nap repository-aktivitás nélkül kikapcsolódnak.
- Hostolt cron-szolgáltatások. Sok szolgáltatás létezik, amelynek egyetlen feladata, hogy időzítetten hívjon egy URL-t. Mielőtt ráhagyatkoznál, ellenőrizd a megbízhatóságot, a minimális időközt és az értesítéseket.
- A felhőszolgáltatód ütemezője. Ha már használsz egy nagy felhőszolgáltatót, lesz nála menedzselt ütemező, amely HTTPS-végpontot tud hívni.
- Hostolt feladat- vagy workflow-szolgáltatás. Ezek egyesítik az ütemezést, a sorokat és az újrapróbálkozásokat, és minden lépésnél hívják a végpontjaidat. Az árakat és korlátokat az egyes szolgáltatók oldalán hasonlítsd össze.
3. minta: hagyd a szolgáltatóra
Néha a legjobb háttérfeladat az, amelyiket egyáltalán nem kell futtatni:
- Fizetések. A Stripe újrapróbálja a sikertelen előfizetési fizetéseket, és webhookokat küld; te reagálsz, nem kérdezgetsz. Lásd: mi a webhook.
- E-mail. A szolgáltatók sorba állítják és újrapróbálják a kézbesítést, amint átadtad nekik az üzenetet.
- Tömeges AI-munka. Az OpenAI és az Anthropic kötegelt API-kat kínál a nem sürgős kérésekhez, amelyeket beküldesz, és később összegyűjtesz.
Promptok az AI-építőnek
Sorhoz:
Adj hozzá háttérfeladat-sort az adatbázisunkban lévő jobs táblával (típus, JSON payload, állapot, attempts, run_after, last_error). Amikor egy felhasználó regisztrál, szúrj be egy send_welcome_email feladatot ugyanabban a tranzakcióban, ahelyett hogy azonnal küldenéd. Adj hozzá egy processJobs(limit) függvényt, amely az esedékes feladatokat SELECT ... FOR UPDATE SKIP LOCKED használatával veszi át, futtatja őket, és a hibákat 1, 5 és 30 perc múlva újrapróbálja, 4 próbálkozás után failed állapotba téve őket.
Ütemezett indítóhoz:
Adj hozzá egy POST /api/cron/tick végpontot, amelyet a CRON_SECRET titokból származó bearer token véd; utasíts el minden kérést token nélkül. Minden hívás futtassa a processJobs(100) függvényt, és küldje el a következő 24 órában esedékes, még nem küldött foglalási emlékeztetőket, rögzítve az elküldötteket, hogy semmi ne menjen ki kétszer. Adj vissza JSON összefoglalót arról, mi futott. Majd írj egy GitHub Actions workflow-t, amely 15 percenként hívja ezt a végpontot, és az URL-t és a tokent a repository titkaiból olvassa.
Gyakori hibák
- A
setInterval-ra való támaszkodás. Csendben megáll, amikor a szerver elalszik vagy újraindul, és duplázódik, ha két példány fut. - Védetlen cron-végpont. Bárki, aki megtalálja, elindíthatja a feladataidat, vagy megnövelheti az e-mail-számládat.
- Nem idempotens feladatok. Az újrapróbálkozások és a duplikált ütemezői hívások meg fognak történni. Ehhez tervezz.
- Nincs hiba-láthatóság. Egy feladat, amely egy hétig csendben hibázik, rosszabb, mint az, amely hangosan jelez. Naplózd a hibákat, és riassz ismétlődő hibáknál.
- Hosszú futások egyetlen kérésben. A kérések időtúllépést kapnak. Dolgozz köteg-ben.
- Túl gyakori ütemezés. Nullára skálázódó tárhelyen minden hívás felébreszti és számlázza az alkalmazást. Igazítsd az időközt a valódi igényhez.
- Időzónák. A „reggel 9” mást jelent az ütemezőnek (gyakran UTC) és a felhasználóidnak. Az időket UTC-ben tárold, és felhasználónként alakítsd át.
- Titkok a workflow-fájlban. A tokeneket az ütemező titoktárában tartsd. Lásd: hogyan őrizd meg biztonságban az API-kulcsaidat.
Ellenőrzőlista
- A lassú munka ki van véve a felhasználói kérésekből
- A feladatok tartósan tárolódnak, nem csak a memóriában
- Újrapróbálkozás növekvő késleltetéssel és maximummal
- Minden feladat biztonságosan futtatható kétszer
- Az ütemezett végpontot titkos token védi
- Minden futás korlátos köteget dolgoz fel
- A sikertelen feladatok láthatók, riasztásokkal
- Az ütemezési időköz a tárhelyköltséget is figyelembe véve lett kiválasztva
- Az idők UTC-ben vannak tárolva
Háttérfeladatok a Mythexben
A Mythex dokumentációja nem ír le ütemezett vagy cron feladatokat, a közzétett alkalmazások és adatbázisaik pedig tétlenség esetén elalszanak, és a következő kérésnél ébrednek fel (lásd: Hosting limits). Ezért ne támaszkodj az alkalmazáson belüli időzítőkre. A működő megoldás a fenti: kérj az ügynöktől egy jobs táblát és egy tokennel védett végpontot, majd irányíts egy külső ütemezőt a közzétett URL-edre. A tokent projekt-titokként tárold, és ne feledd, hogy minden felébredés krediteket költ arra az időre, amíg az alkalmazás és az adatbázis ébren van, ezért válassz ésszerű időközt. Ha az alkalmazásodnak ehhez API-backendre van szüksége, a REST API backend recept jó kiindulópont, a végpontok tervezéséről pedig a hogyan építs REST API-t útmutató ír. Ha a terméked magja az állandóan futó worker vagy bot, egy tartós folyamatokra épült tárhely jobban illhet hozzád.
Kérdések
Mi az a háttérfeladat?
A háttérfeladat olyan munka, amelyet az alkalmazásod a felhasználó által várt kérésen kívül végez, például e-mailek küldése, képek átméretezése, jelentések készítése vagy adatok szinkronizálása. A felhasználó gyors választ kap, a feladat pedig külön fut, és hiba esetén újrapróbálható.
Hogyan futtatok ütemezett feladatot, ha a tárhelyemen nincs cron?
Adj hozzá egy védett végpontot, amely elvégzi a munkát, majd egy külső ütemező hívja meg időzítetten. Lehetőségek: egy ütemezett GitHub Actions workflow, egy hostolt cron-szolgáltatás vagy a felhőszolgáltatód ütemezője. A végpontot titkos tokennel védd.
Használhatok setInterval vagy setTimeout függvényt ütemezett feladatokra?
Csak kis, nem kritikus feladatokra, olyan szerveren, amely mindig fut. Ha a szerver újraindul, nullára skálázódik vagy több példányban fut, az időzítők elvesznek, vagy többször futnak le. Tárold az ütemezett munkát adatbázisban, vagy használj ütemezőt.
Támogatja a Mythex a cron feladatokat?
A Mythex dokumentációja nem ír le ütemezett vagy cron feladatokat, a közzétett alkalmazások pedig tétlenség esetén elalszanak. A megbízható megoldás az, hogy egy külső ütemező meghívja az alkalmazásodban lévő védett végpontot, ami felébreszti az alkalmazást és lefuttatja a munkát.