Vissza a bloghoz

Cron jobok monitorozása: a heartbeat minta a gyakorlatban

· 6 perc olvasás

A HTTP monitorozás nem észleli, hogy egy éjszakai cron elhasalt. A heartbeat minta megfordítja az irányt: a cron jelentkezik a monitorozásnál, és ha nem hív be időben, értesítést kapsz.

Cron jobok monitorozása: a heartbeat minta a gyakorlatban

A probléma: háttérfeladatok HTTP endpoint nélkül

Egy tipikus backendnek több útvonala van:

  • Webes kérések (HTTP/HTTPS a szerverre) - ezeket uptime check-kel monitorozod.
  • Cron jobok (napi mentés, havi számlázás, óránkénti szinkronizáció) - nincs HTTP endpointjuk, a külső monitorozás nem tudja figyelni őket.
  • Workerek (Celery, BullMQ, Sidekiq), amelyek egy sort dolgoznak fel - szintén HTTP nélkül.

Amikor egy cron elhasal (elgépelés a crontabban, tele lemez, hiányzó környezeti változó (environment variable) vagy importálási hiba egy függőség frissítése (dependency upgrade) után), senki nem értesít. Hétfő reggel jössz rá, amikor észreveszed, hogy a hétvégén egyetlen számlát sem küldött ki a rendszer.

A heartbeat minta: a cron pingeli a monitorozást

Az elv fordított a normál monitorozáshoz képest:

  1. A monitorozó szolgáltatásban létrehozol egy heartbeat monitort egy elvárt intervallummal (például "60 percenként").
  2. Kapsz egy egyedi heartbeat URL-t: https://epulz.io/heartbeat/abc123xyz.
  3. A cron jobodban, egy sikeres futás végén, meghívod ezt az URL-t (HTTP GET vagy POST).
  4. Ha a ping nem érkezik meg az elvárt időn belül (plusz türelmi időszak), a monitorozás értesít.

Gyakorlati példa: heartbeat egy cron jobból

# /etc/crontab
0 3 * * * www-data /usr/local/bin/backup.sh && curl -fsS -m 10 \
  https://epulz.io/heartbeat/abc123xyz > /dev/null

A kulcs az && operátor: a heartbeat csak akkor megy ki, ha a backup.sh 0 kilépési kóddal fejeződik be. Ha a szkript elhasal, a ping nem érkezik meg, és egy órán belül értesítést kapsz.

Tipp: Alaposabb lefedettségért adj hozzá egy "start" heartbeatet is:

curl -fsS -m 10 https://epulz.io/heartbeat/backup-start-xyz > /dev/null
/usr/local/bin/backup.sh && \
  curl -fsS -m 10 https://epulz.io/heartbeat/backup-done-xyz > /dev/null

A monitorozás így meg tudja különböztetni az "elindult, de nem fejeződött be" (a szkript lefagyott) esetet a "soha nem indult el" (a cron job le sem futott) esettől.

Python: requests + try/except

import os, requests
HEARTBEAT_URL = os.environ["HEARTBEAT_URL"]

def sync_data():
    # ... your logic ...
    pass

try:
    sync_data()
    requests.get(HEARTBEAT_URL, timeout=10)
except Exception as e:
    # A heartbeat nem megy ki - a monitorozás értesít
    raise

Node.js: async / await

const HEARTBEAT_URL = process.env.HEARTBEAT_URL;

async function nightlyJob() {
  await processInvoices();
  await fetch(HEARTBEAT_URL, { signal: AbortSignal.timeout(10000) });
}

nightlyJob().catch(err => {
  console.error(err);
  process.exit(1);
});

Türelmi időszak: mennyi időt adj az értesítés előtt

A heartbeat monitornak szüksége van bizonyos toleranciára. A cron időnként a szokásosnál tovább fut, a hálózatnak van késleltetése, és az NTP szinkronizáció kissé eltolódhat. A türelmi időszak az az idő az elvárt intervallum letelte után, amíg a monitorozás még vár, mielőtt értesítést indít.

Gyakorlati értékek:

  • Óránkénti cron: intervallum 60 perc + türelem 10 perc
  • Napi mentés (átlagosan 20 perc): intervallum 1440 perc + türelem 60 perc
  • Heti report: intervallum 10080 perc + türelem 360 perc (6 ó)

Túl szűk türelem = hamis értesítések (false positive). Túl laza = késleltetett értesítés pont akkor, amikor a feladat valóban elhasal.

Hol segít a legtöbbet a heartbeat minta

  • Éjszakai DB mentések
  • Szinkronizáció külső API-kkal (CRM, accounting, payment)
  • Report kalkulációk
  • Cleanup feladatok (régi munkamenetek, logok, ideiglenes fájlok törlése)
  • Hosszan futó workerek healthcheck ciklusa
  • Ütemezett e-mailek, hírlevelek, számlázás

Konklúzió

A háttérfeladatok (background) gyakran kritikusabbak, mint maga a weboldal, mégis a monitorozás vakfoltjai maradnak. A heartbeat minta megvalósítása mindössze öt percet vesz igénybe (csak adj egy curl-t a cron sor végére), és ugyanazt a biztonságot adja, mint a frontend uptime monitorozása.

Gyors emlékeztető: cron szintaxis

A heartbeat hibák többsége valójában cron hiba - a ping soha nem fut le, mert rossz volt az ütemezés. Az öt mező:

┌── perc (0-59)
│ ┌── óra (0-23)
│ │ ┌── a hónap napja (1-31)
│ │ │ ┌── hónap (1-12)
│ │ │ │ ┌── a hét napja (0-7, 0 és 7 = vasárnap)
│ │ │ │ │
* * * * *  parancs
Kifejezés Lefut
*/5 * * * * 5 percenként
0 * * * * minden óra elején
0 3 * * * minden nap 03:00-kor
0 3 * * 1 minden hétfőn 03:00-kor
30 2 1 * * a hónap első napján 02:30-kor

A klasszikus csapda: a */5 az óra mezőben nem azt jelenti, hogy "mostantól 5 óránként", hanem az öttel osztható órákat (0, 5, 10, 15, 20). Ha a monitor elvárt intervalluma és a valós cron ütemezés nem egyezik, fantom értesítéseket kapsz.

A "dead man's switch" elv

A heartbeat minta egy dead man's switch (holtember-kapcsoló): a riasztás a csend. Ez megfordítja a szokásos hibamódot. A normál monitorozás csendben is elhasalhat - ha maga a monitorozó szerver esik ki, egyszerűen abbahagyja az értesítések küldését, és te sosem tudsz róla. A heartbeat ennek az ellentéte: az értesítés kiváltója egy elvárt jelzés hiánya, így egy olyan feladat, amely teljesen leáll (az egész szerver ki van kapcsolva, a cron démon tiltva van, a gépet leselejtezték és elfelejtették), pontosan az az eset, amelyet a legjobban elkap.

A cronon túl: más ütemezők

A minta ugyanaz, függetlenül attól, mi indítja a feladatot: - systemd timerek - add a curl-t az ExecStart lánchoz vagy az ExecStartPost=-hoz. Párosítsd az OnCalendar= timert egy megfelelő heartbeat intervallummal. - Kubernetes CronJob - a konténer utolsó lépése pingeli a heartbeat URL-t. Ha a pod elhasal vagy egyáltalán nem ütemeződik (rossz node selector, image pull hiba), a ping hiányzik, és értesítést kapsz. - Windows Task Scheduler - fejezd be a feladatot az Invoke-WebRequest -Uri $env:HEARTBEAT_URL -TimeoutSec 10 PowerShell paranccsal. - CI / ütemezett pipeline-ok - egy éjszakai GitHub Actions vagy GitLab schedule utolsó lépésként pingelheti a heartbeatet, megerősítve, hogy a pipeline lefutott és át is ment.

Gyakori anti-minták

  • Ping az elején, nem a végén. A munka előtt küldött heartbeat csak azt bizonyítja, hogy a feladat elindult. Tedd a munka mögé, sikerhez kötve (&&), hogy egy futás közbeni összeomlás szintén visszatartsa a pinget.
  • A kilépési kód figyelmen kívül hagyása. A backup.sh; curl ... (pontosvessző) akkor is elküldi a pinget, ha a mentés elhasalt. Mindig &&-t használj.
  • A curl hibák csendes elnyelése. A -fsS hatására a curl HTTP hiba esetén hangosan elhasal, így a feladatod logjai megmutatják, hogy a heartbeatet nem sikerült kézbesíteni (hálózati probléma a gépen).
  • Egy heartbeat tíz feladatra. Ha öt cron egy URL-en osztozik, nem tudod, melyik állt le. Adj minden ütemezett feladatnak saját heartbeatet. Ha ugyanahhoz a szolgáltatáshoz HTTP endpointot is kiteszel, párosítsd a heartbeatet egy szokásos uptime check-kel és egy port ellenőrzéssel a worker portján, hogy lefedd a "a folyamat fut" és a "az ütemezett futás megtörtént" esetet is.

Konkrét forgatókönyv: a néma mentési hiba

A heartbeat tankönyvi esete így néz ki. Egy éjszakai pg_dump egy csatolt kötetre ír. Hónapokig működik. Aztán a kötet megtelik, a pg_dump nem nulla kóddal lép ki, és mivel a cron sor sima pontosvesszőt használt, a heartbeat mégis kimegy, és a dashboard zöld marad. Három héttel később az adatbázis sérült, és nincs használható mentés, mert minden "sikeres" mentés azóta, hogy a lemez megtelt, nulla bájtos fájl volt. A heartbeat minta ezt már az első éjszaka elkapja, de csak ha helyesen van bekötve: kösd a pinget &&-hez, hogy a nem nulla kilépés visszatartsa, és fontold meg a kimenet ellenőrzését is, ne csak a kilépési kódét. Egy mentési szkript kiléphet 0 kóddal, és mégis csonka fájlt állíthat elő. Egy védekezőbb sor ellenőrzi, hogy a dump nem triviális, még a siker jelzése előtt:

/usr/local/bin/backup.sh && \
  test "$(stat -c%s /backups/db.sql.gz)" -gt 1000000 && \
  curl -fsS -m 10 https://epulz.io/heartbeat/abc123xyz > /dev/null

Most a heartbeat csak akkor érkezik meg, ha a szkript sikeres volt és az eredményfájl több mint 1 MB. Bármi kisebb, és a ping visszatartódik, te pedig a türelmi időszakon belül kapsz értesítést három hét múlva helyett.

Kezdd el monitorozni a cron jobokat

Az ePulz.io támogatja a heartbeat check-eket konfigurálható türelmi időszakkal. 7 nap ingyen.

Monitorozás indítása →

Kapcsolódó

Megosztás: Link másolva

Próbálja ki az ePulz.io-t ingyen - 7 nap bankkártya nélkül.

Fiók létrehozása