Kaip vykdyti fonines užduotis žiniatinklio programėlėje: eilės, planuotojai ir cron
Norėdami vykdyti fonines užduotis žiniatinklio programėlėje, pirmiausia padalinkite darbą į dvi rūšis. Paleidžiamos užduotys (išsiųsti sveikinimo laišką, apdoroti įkėlimą) gali būti įrašytos į užduočių eilę, dažnai duomenų bazės lentelę, ir apdorotos darbuotojo su pakartojimais. Planuotos užduotys (naktinė ataskaita, priminimai kas 15 minučių) reikalauja kažko, kas paleidžiama pagal tvarkaraštį: hostingo cron funkcijos arba išorinio planuotojo, kuris kviečia apsaugotą galinį tašką jūsų programėlėje. Visada darykite užduotis saugias paleisti du kartus, fiksuokite klaidas ir niekada nesiremkite laikmačiu serveryje, kuris gali užmigti ar paleistis iš naujo.
Šis vadovas paaiškina galimybes, kada kiekviena tinka ir kaip jas nustatyti su DI programėlių kūrėju, įskaitant hostus, mažinančius iki nulio.
Kas laikoma fonine užduotimi
Viskas, kas lėta, nepatikima ar nereikalinga tiesioginiam naudotojo atsakymui:
- El. laiškų, pranešimų ir kvitų siuntimas
- Nuotraukų keitimas dydžiu, vaizdo konvertavimas, PDF generavimas
- Lėtų trečiųjų šalių API kvietimai, įskaitant DI modelius ilgoms užduotims
- Duomenų importavimas ar sinchronizavimas iš kitos sistemos
- Naktinis valymas, ataskaitos ir priminimai
Jei tai daroma užklausos viduje, puslapiai lėtėja ir tampa trapūs: jei el. pašto teikėjas neveikia, naudotojo registracija nepavyksta. Perkėlus į foną naudotojas gauna momentinį atsakymą, o užduotį galima pakartoti.
Pasirinkimai
| Pasirinkimas | Kaip veikia | Privalumai | Trūkumai |
|---|---|---|---|
| Paleidimas ir pamiršimas tame pačiame procese | Atsakote, tada tęsiate darbą serveryje | Jokio nustatymo | Prarandama, jei serveris sustoja; nėra pakartojimų |
Procese veikiantis laikmatis (setInterval, setTimeout) | Laikmatis veikiančiame serveryje | Labai paprasta | Neveikia, kol snaudžia; dubliuojasi, jei kopijų kelios |
| Duomenų bazės grįsta eilė | Užduotys įrašomos kaip eilutės; darbuotojas jas paima ir vykdo | Naudoja turimą duomenų bazę; patvarumas; lengva tikrinti | Pakartojimus ir užrakinimą kuriate patys; reikia, kas paleistų darbuotoją |
| Atskira eilė (Redis pagrindu ar valdoma) | Eilės paslauga ir darbuotojai | Brandūs pakartojimo ir planavimo funkcijos | Dar viena paslauga, kurią reikia valdyti ir mokėti už ją |
| Hostinguojama darbų ar darbo srautų paslauga | Trečioji šalis kviečia jūsų galinius taškus su pakartojimais ir tvarkaraščiais | Planavimą ir pakartojimus tvarko jie | Priklausomybė nuo tiekėjo; dar viena paskyra ir raktas |
| Išorinis planuotojas, kviečiantis galinį tašką | Kitur veikiantis laikmatis siunčia HTTP užklausą pagal tvarkaraštį | Veikia bet kuriame hoste, įskaitant mažinamus iki nulio | Minimalūs intervalai ir vėlavimai; galinį tašką reikia apsaugoti |
| Hosto integruotas cron | Platforma paleidžia komandą pagal tvarkaraštį | Paprasta, kur yra | Ne kiekvienas hostas tai siūlo |
Vienintelio teisingo atsakymo nėra. Mažai programėlei dažnai pakanka tik duomenų bazės eilės ir išorinio planuotojo.
Kodėl hostai, mažinantys iki nulio, keičia vaizdą
Daugelis šiuolaikinių hostų užmigdo jūsų programėlę, kai niekas jos nenaudoja, ir pažadina kitos užklausos metu. Tai sutaupo pinigų, bet snaudžiantis serveris nevykdo jokio kodo: laikmačiai neveikia, darbuotojai neklausia eilės. Tokiuose hostuose suplanuotas darbas turi prasidėti nuo gaunamos užklausos, o lengviausias tokios užklausos šaltinis – išorinis planuotojas. Kiekvienas iškvietimas pažadina programėlę (ir dažnai jos duomenų bazę), todėl kvietimas kas minutę kainuoja daugiau nei kas 15 minučių. Pasirinkite lėčiausią tvarkaraštį, kuris tenkina poreikį.
Šablonas 1: duomenų bazės užduočių eilė
Paleidžiamoms užduotims:
- Sukurkite
jobslentelę: tipas, duomenys (JSON), būsena (pending,running,done,failed), bandymai, run_after, last_error, laiko žymos. - Kai kas nors įvyksta, įrašykite užduoties eilutę toje pačioje transakcijoje kaip ir pakeitimas, kuris ją sukėlė, kad jos pavyktų arba nepavyktų kartu.
- Darbuotojas paima paruoštas užduotis, pažymi jas
running, atlieka darbą ir pažymidone. - Nepavykus padidinkite
attempts, nustatykite vėlesnįrun_after(pavyzdžiui, po 1, 5, tada 30 minučių) ir įrašykite klaidą. Pasiekus maksimalų skaičių, pažymėkitefailedir įspėkite ką nors.
Jei galbūt vienu metu veiks daugiau nei vienas darbuotojas, užduotys turi būti paimamos saugiai. Postgres duomenų bazėje SELECT ... FOR UPDATE SKIP LOCKED leidžia kiekvienam darbuotojui paimti skirtingas eilutes be susidūrimų.
Kas paleidžia darbuotoją? Visada įjungtame serveryje – ciklas atskirame procese. Hoste, mažinančiame iki nulio, planuoto galinio taško iš 2 šablono kiekvienas iškvietimas gali apdoroti paruoštų užduočių partiją.
Šablonas 2: išorinis planuotojas, kviečiantis jūsų programėlę
Planuotoms užduotims:
- Pridėkite galinį tašką, pavyzdžiui
POST /api/cron/send-reminders. - Apsaugokite jį: reikalaukite paslapties žetono antraštėje, saugomo kaip paslaptis abiejose pusėse, ir atmetkite viską kita.
- Padarykite jį idempotentišku: paleidus du kartus per tą pačią minutę, priminimai neturi būti išsiųsti du kartus. Įrašykite, kas išsiųsta.
- Laikykite kiekvieną iškvietimą trumpą: apdorokite partiją (tarkime, 100 elementų) ir leiskite kitam iškvietimui paimti likusius.
- Nukreipkite planuotoją į jį.
Planuotojo pasirinkimai:
- GitHub Actions suplanuoti darbo srautai. Nemokami GitHub naudojimo limitų ribose. Pagal GitHub dokumentaciją 2026 m. rugsėjį trumpiausias intervalas yra kartą per 5 minutes, paleidimai gali vėluoti įprastu metu (ypač kiekvienos valandos pradžioje), tvarkaraščiai pagal numatytuosius nustatymus naudoja UTC, o suplanuoti darbo srautai viešoje saugykloje išjungiami po 60 dienų be saugyklos veiklos.
- Hostinguojamos cron paslaugos. Yra daug paslaugų, kurių vienintelis darbas – iškviesti URL pagal tvarkaraštį. Prieš jomis pasitikėdami patikrinkite patikimumą, minimalų intervalą ir įspėjimus.
- Jūsų debesijos teikėjo planuotojas. Jei jau naudojate didelį debesijos teikėją, jis turės valdomą planuotoją, galintį iškviesti HTTPS galinį tašką.
- Hostinguojama darbų ar darbo srautų paslauga. Jos sujungia planavimą, eiles ir pakartojimus bei kiekvienam žingsniui kviečia jūsų galinius taškus. Kainas ir limitus palyginkite kiekvieno tiekėjo svetainėje.
Šablonas 3: leiskite teikėjui tai atlikti
Kartais geriausia fono užduotis – jokia:
- Mokėjimai. Stripe pakartoja nepavykusius prenumeratos mokėjimus ir siunčia webhook'us; jūs reaguojate, o ne klausinėjate. Žr. kas yra webhook.
- El. paštas. Teikėjai eilina ir pakartoja pristatymą, kai jiems perduodate laišką.
- Masinis DI darbas. OpenAI ir Anthropic siūlo paketinius API neskubiems užklausimams, kuriuos pateikiate ir surenkate vėliau.
Užklausos jūsų DI kūrėjui
Eilei:
Pridėk fono užduočių eilę, naudodamas
jobslentelę mūsų duomenų bazėje (tipas, JSON duomenys, būsena, bandymai, run_after, last_error). Kai naudotojas registruojasi, įrašyk send_welcome_email užduotį į tą pačią transakciją vietoj siuntimo tiesiogiai. Pridėk funkciją processJobs(limit), kuri paima paruoštas užduotis naudodama SELECT ... FOR UPDATE SKIP LOCKED, jas vykdo ir pakartoja nesėkmes po 1, 5 ir 30 minučių, pažymėdama jas kaip nepavykusias po 4 bandymų.
Planuotam paleidimui:
Pridėk POST /api/cron/tick, apsaugotą bearer žetonu iš paslapties CRON_SECRET; atmesk bet kokią užklausą be jo. Kiekvienas iškvietimas vykdo processJobs(100) ir siunčia rezervacijos priminimus, kurie turi įvykti per artimiausias 24 valandas ir dar nebuvo išsiųsti; išsiųstus priminimus įrašyk, kad nieko nesiųstume dukart. Grąžink JSON santrauką, ką įvykdė. Tada parašyk GitHub Actions darbo srautą, kuris kviečia šį galinį tašką kas 15 minučių, skaitydamas URL ir žetoną iš saugyklos paslapčių.
Dažnos klaidos
- Pasikliovimas
setInterval. Jis tyliai sustoja, kai serveris snaudžia ar paleidžiamas iš naujo, ir dubliuojasi, kai veikia kelios kopijos. - Neapsaugotas cron galinis taškas. Bet kas, kas jį suras, galės paleisti jūsų užduotis ar padidinti jūsų el. pašto sąskaitą.
- Užduotys, kurios nėra idempotentiškos. Pakartojimai ir dvigubi planuotojo iškvietimai įvyks. Projektuokite jiems.
- Nėra matomumo klaidoms. Užduotis, kuri savaitę tyliai nepavyksta, yra blogesnė nei ta, kuri garsiai praneša. Fiksuokite klaidas ir įspėkite apie pasikartojančias nesėkmes.
- Ilgi paleidimai vienoje užklausoje. Užklausos baigiasi per laiką. Apdorokite partijomis.
- Per dažnas planavimas. Kiekvienas iškvietimas hoste, mažinančiame iki nulio, pažadina ir apmokestina programėlę. Suderinkite intervalą su tikru poreikiu.
- Laiko juostos. „9 val. ryto“ reiškia skirtingus dalykus jūsų planuotojui (dažnai UTC) ir naudotojams. Laikus saugokite UTC ir konvertuokite kiekvienam naudotojui.
- Paslaptys darbo srauto faile. Laikykite žetonus planuotojo paslapčių saugykloje. Žr. kaip saugoti API raktus.
Kontrolinis sąrašas
- Lėtas darbas perkeltas iš naudotojo užklausų
- Užduotys saugomos patvariai, ne tik atmintyje
- Pakartojimai su didėjančiais vėlavimais ir maksimumu
- Kiekviena užduotis saugi paleisti du kartus
- Planuotas galinis taškas apsaugotas paslapties žetonu
- Kiekvienas paleidimas apdoroja ribotą partiją
- Nepavykusios užduotys matomos, su įspėjimais
- Tvarkaraščio intervalas parinktas atsižvelgiant į hostingo išlaidas
- Laikai saugomi UTC
Fono užduotys Mythex
Mythex dokumentacijoje planuotos ar cron užduotys neaprašytos, o paskelbtos programėlės ir jų duomenų bazės snaudžia, kai neaktyvios, ir pabunda kitos užklausos metu (žr. Hostingo limitai). Todėl nesiremkite laikmačiais savo programėlės viduje. Veikia tas metodas, kurį aprašėme aukščiau: paprašykite agento sukurti užduočių lentelę ir galinį tašką, apsaugotą žetonu, tada nukreipkite išorinį planuotoją į savo paskelbtą URL. Žetoną saugokite kaip projekto paslaptį ir atsiminkite, kad kiekvienas pabudimas kainuoja kreditus už laiką, kurį programėlė ir duomenų bazė buvo budrios, todėl pasirinkite protingą intervalą. Jei jūsų programėlei tam reikia API serverio, REST API backend receptas yra pradžios taškas, o kaip sukurti REST API aprašo galinių taškų kūrimą. Jei jūsų produkto esmė – nuolat veikiantys darbuotojai ar botai, geriau gali tikti hostas, skirtas ilgai veikiantiems procesams.
Klausimai
Kas yra fonas užduotis?
Fono užduotis – tai darbas, kurį programėlė atlieka už naudotojo laukiamos užklausos ribų, pavyzdžiui siunčia el. laiškus, keičia nuotraukų dydį, generuoja ataskaitas ar sinchronizuoja duomenis. Naudotojas gauna greitą atsakymą, o užduotis vykdoma atskirai ir gali būti pakartota, jei nepavyko.
Kaip paleisti planuotą užduotį, jei mano hostingas neturi cron?
Pridėkite apsaugotą galinį tašką, kuris atlieka darbą, ir leiskite išoriniam planuotojui jį iškviesti pagal tvarkaraštį. Pasirinkimai: suplanuotas GitHub Actions darbo srautas, hostinguojama cron paslauga arba debesijos teikėjo planuotojas. Apsaugokite galinį tašką slaptu žetonu.
Ar galiu naudoti setInterval ar setTimeout planuotoms užduotims?
Tik mažoms, nesvarbioms užduotims serveryje, kuris visada veikia. Jei serveris paleidžiamas iš naujo, mažinamas iki nulio ar veikia keliomis kopijomis, laikmačiai prarandami arba veikia daugiau nei vieną kartą. Saugokite suplanuotus darbus duomenų bazėje arba naudokite planuotoją.
Ar Mythex palaiko cron užduotis?
Mythex dokumentacijoje planuotos ar cron užduotys neaprašytos, o paskelbtos programėlės snaudžia, kai neaktyvios. Patikimas būdas – išorinis planuotojas, kviečiantis apsaugotą galinį tašką jūsų programėlėje; jis pažadina programėlę ir atlieka darbą.