Bloga geri dön

Cron işlerini izleme: pratikte heartbeat deseni

· 6 dk okuma

HTTP izleme, gece çalışan bir cron'un çöktüğünü size söylemez. Heartbeat deseni yönü tersine çevirir: cron kendini izlemeye bildirir ve zamanında aramazsa bir uyarı alırsınız.

Cron işlerini izleme: pratikte heartbeat deseni

Sorun: HTTP endpoint'i olmayan arka plan işleri

Tipik bir backend'in birkaç yolu vardır:

  • Web istekleri (sunucuya HTTP/HTTPS) - bunları bir uptime check ile izlersiniz.
  • Cron işleri (günlük yedek, aylık faturalama, saatlik senkronizasyon) - bunların HTTP endpoint'i yoktur, harici izleme onları takip edemez.
  • Bir kuyruğu işleyen worker'lar (Celery, BullMQ, Sidekiq) - onlar da HTTP'siz.

Bir cron çöktüğünde (crontab'da bir yazım hatası, dolu disk, eksik bir ortam değişkeni (environment variable) veya bağımlılık yükseltmesinden (dependency upgrade) sonra bir import hatası), kimse sizi uyarmaz. Bunu Pazartesi sabahı, hafta sonu hiç fatura gitmediğini fark ettiğinizde öğrenirsiniz.

Heartbeat deseni: cron izlemeyi pingler

İlke, normal izlemenin tersidir:

  1. İzleme servisinde beklenen bir aralığa sahip bir heartbeat monitörü oluşturursunuz (örneğin "her 60 dakikada bir").
  2. Benzersiz bir heartbeat URL'si alırsınız: https://epulz.io/heartbeat/abc123xyz.
  3. Cron işinizde, başarılı bir çalışmanın sonunda bu URL'yi çağırırsınız (HTTP GET veya POST).
  4. Ping beklenen süre içinde (artı bir grace süresi) gelmezse, izleme sizi uyarır.

Pratik örnek: bir cron işinden heartbeat

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

Anahtar, && operatörüdür: heartbeat yalnızca backup.sh çıkış kodu 0 ile bittiğinde gönderilir. Betik başarısız olursa ping gelmez ve bir saat içinde bir uyarı alırsınız.

İpucu: Daha kapsamlı bir kapsama için bir de "start" heartbeat'i ekleyin:

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

İzleme o zaman "başladı ama bitmedi" (betik takıldı) durumunu "hiç başlamadı" (cron işi çalışmadı) durumundan ayırt edebilir.

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:
    # Heartbeat gönderilmez - izleme sizi uyarır
    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);
});

Grace süresi: uyarıdan önce ne kadar süre tanımalı

Bir heartbeat monitörünün belli bir toleransa ihtiyacı vardır. Cron bazen her zamankinden uzun sürer, ağın gecikmesi vardır ve NTP senkronizasyonu biraz kaymış olabilir. Grace süresi, beklenen aralık dolduktan sonra izlemenin bir uyarı tetiklemeden önce hâlâ beklediği süredir.

Pratik değerler:

  • Saatlik cron: aralık 60 dk + grace 10 dk
  • Günlük yedek (ortalama 20 dk): aralık 1440 dk + grace 60 dk
  • Haftalık rapor: aralık 10080 dk + grace 360 dk (6 sa)

Çok dar bir grace = yanlış uyarılar (false positive). Çok geniş = işin gerçekten çöktüğü anda gecikmiş bir uyarı.

Heartbeat deseni en çok nerede yardımcı olur

  • Gece DB yedekleri
  • Harici API'lerle senkronizasyon (CRM, muhasebe, ödeme)
  • Rapor hesaplamaları
  • Cleanup işleri (eski oturumların, logların, geçici dosyaların silinmesi)
  • Uzun süre çalışan worker'ların healthcheck döngüsü
  • Zamanlanmış e-postalar, bültenler, faturalama

Sonuç

Arka plan (background) işleri çoğu zaman sitenin kendisinden daha kritiktir, ama izlemenin kör noktası olarak kalır. Heartbeat deseninin uygulanması yalnızca beş dakika sürer (cron satırının sonuna curl eklemeniz yeterli) ve frontend'in uptime izlemesiyle aynı güvenceyi sağlar.

Hızlı hatırlatma: cron sözdizimi

Heartbeat hatalarının çoğu aslında cron hatalarıdır - zamanlama yanlış olduğu için ping hiç tetiklenmez. Beş alan şunlardır:

┌── dakika (0-59)
│ ┌── saat (0-23)
│ │ ┌── ayın günü (1-31)
│ │ │ ┌── ay (1-12)
│ │ │ │ ┌── haftanın günü (0-7, 0 ve 7 = Pazar)
│ │ │ │ │
* * * * *  komut
İfade Çalışır
*/5 * * * * her 5 dakikada bir
0 * * * * her saatin başında
0 3 * * * her gün 03:00'te
0 3 * * 1 her Pazartesi 03:00'te
30 2 1 * * ayın ilk günü 02:30'da

Klasik tuzak: saat alanındaki */5, "şu andan itibaren her 5 saatte bir" anlamına gelmez, beşe bölünebilen saatleri (0, 5, 10, 15, 20) ifade eder. Monitörün beklenen aralığı ile gerçek cron zamanlaması uyuşmazsa, hayalet uyarılar alırsınız.

"Dead man's switch" ilkesi

Heartbeat deseni bir dead man's switch'tir (ölü adam şalteri): alarm, sessizliktir. Bu, olağan arıza modunu tersine çevirir. Normal izleme sessizce başarısız olabilir - izleme sunucusunun kendisi çökerse, basitçe uyarı göndermeyi bırakır ve siz bunu hiç öğrenemezsiniz. Heartbeat bunun tersidir: bir uyarının tetikleyicisi, beklenen bir sinyalin yokluğudur, dolayısıyla tamamen çalışmayı bırakan bir iş (tüm sunucu kapalı, cron daemon'ı devre dışı, makine hizmet dışı bırakılıp unutulmuş) tam da en iyi yakaladığı durumdur.

Cron'un ötesinde: diğer zamanlayıcılar

İşi ne tetiklerse tetiklesin desen aynıdır: - systemd timer'ları - curlExecStart zincirine veya ExecStartPost='a ekleyin. OnCalendar= timer'ını eşleşen bir heartbeat aralığıyla eşleştirin. - Kubernetes CronJob - container'ın son adımı heartbeat URL'sini pingler. Pod çökerse veya hiç zamanlanmazsa (yanlış node selector, image pull hatası), ping eksik kalır ve bir uyarı alırsınız. - Windows Task Scheduler - görevi Invoke-WebRequest -Uri $env:HEARTBEAT_URL -TimeoutSec 10 PowerShell komutuyla bitirin. - CI / zamanlanmış pipeline'lar - gece çalışan bir GitHub Actions veya GitLab schedule, son adım olarak heartbeat'i pingleyerek pipeline'ın hem çalıştığını hem de geçtiğini doğrulayabilir.

Yaygın anti-desenler

  • Sonunda değil, başında pinglemek. İşten önce gönderilen bir heartbeat yalnızca işin başladığını kanıtlar. Onu işin arkasına, başarıya bağlı olarak (&&) koyun ki çalışmanın ortasındaki bir çökme de pingi tutsun.
  • Çıkış kodunu yok saymak. backup.sh; curl ... (noktalı virgül), yedek başarısız olsa bile pingi gönderir. Her zaman && kullanın.
  • curl hatalarını sessizce yutmak. -fsS, curl'ün bir HTTP hatasında yüksek sesle başarısız olmasını sağlar, böylece işinizin logları heartbeat'in iletilemediğini gösterir (makinedeki bir ağ sorunu).
  • On iş için tek bir heartbeat. Beş cron tek bir URL'yi paylaşırsa, hangisinin çalışmayı bıraktığını bilemezsiniz. Her zamanlanmış işe kendi heartbeat'ini verin. Aynı servis için bir de HTTP endpoint'i sunuyorsanız, heartbeat'i normal bir uptime check ve worker'ın portu üzerinde bir port kontrolü ile eşleştirin; böylece hem "süreç çalışıyor"u hem de "zamanlanmış çalışma gerçekleşti"yi kapsarsınız.

Somut bir senaryo: sessiz yedek arızası

Bir heartbeat için ders kitabı örneği şöyle görünür. Gece çalışan bir pg_dump, bağlı bir birime yazar. Aylarca çalışır. Sonra birim dolar, pg_dump sıfırdan farklı bir kodla çıkar ve cron satırı düz bir noktalı virgül kullandığı için heartbeat yine de gönderilir ve dashboard yeşil kalır. Üç hafta sonra veritabanı bozulmuştur ve kullanılabilir bir yedek yoktur, çünkü disk dolduğundan beri her "başarılı" yedek sıfır baytlık bir dosyaydı. Heartbeat deseni bunu daha ilk gece yakalar, ama yalnızca doğru bağlandıysa: pingi && ile koşula bağlayın ki sıfırdan farklı bir çıkış onu tutsun ve yalnızca çıkış kodunu değil, çıktıyı da kontrol etmeyi düşünün. Bir yedek betiği kod 0 ile çıkıp yine de kesik bir dosya üretebilir. Daha savunmacı bir satır, başarıyı işaret etmeden önce dump'ın önemsiz olmadığını doğrular:

/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

Artık heartbeat yalnızca betik başarılı olursa ve sonuç dosyası 1 MB'den büyükse gelir. Daha küçük olan her şeyde ping tutulur ve üç hafta sonra değil, grace süresi içinde bir uyarı alırsınız.

Cron işlerinizi izlemeye başlayın

ePulz.io, yapılandırılabilir bir grace süresiyle heartbeat check'leri destekler. 7 gün ücretsiz.

İzlemeyi başlat →

İlgili

Paylaş: Bağlantı kopyalandı

ePulz.io'yu ücretsiz deneyin - 7 gün, kredi kartı gerekmez.

Hesap oluştur