Cron görevleri, basit zamanlanmış görevler için iyi çalışır. Ancak yüksek trafik uygulamalarında güvenilirlik, tekrar deneme mantığı ve gözlemlenebilirlik gerektiğinde, bu görevler bir yük haline gelebilir. Laravel Queues ile Redis kullanımı, bu üç problemi çözer — ve geçiş, çoğu geliştiricinin düşündüğünden daha basittir. Bu makalede, Delhi NCR’deki bir fintech müşterisi için yaptığım spesifik refaktörü belgeliyorum; burada bir cron görevi, zirve saatlerde 40 saniyelik sayfa zaman aşımına neden oluyordu.
Laravel Uygulamalarında Cron Görevlerinin Problemi
Laravel Uygulamalarında Cron Görevlerinin Problemi
Geçtiğimiz yıl bir fintech startup’ından bir Laravel kod tabanı devraldım. Günlük işlem uzlaştırma işlemi, Laravel’in zamanlayıcısı üzerinden her 5 dakikada bir cron görevi olarak çalışıyordu. Düşük trafik günlerinde sorun yoktu. Ancak ay sonlarında 8.000 işlemin uzlaştırılması gerektiğinde, web işçileri donuyor, sıraya giriyor ve yönetici paneli 40 saniye süreyle zaman aşımlarına uğruyordu.
Temel sebep basit: Laravel’deki cron görevleri, web sunucusu sürecinde senkron olarak çalışır. HTTP isteklerini işleyen aynı PHP-FPM işçilerini kullanır.
// Sahip olduğumuz — web sürecinde senkron çalışıyor
// App\Console\Kernel.php dosyasında
$schedule->command('reconcile:transactions')->everyFiveMinutes();
reconcile:transactions 35 saniye veya daha fazla sürdüğünde, o pencere sırasında uygulamayı kullanan kullanıcılar aynı işçi tarafından bekletiliyordu.
Laravel Kuyruğu Çözümü — Nasıl Çalışır
Laravel Kuyruğu Çözümü — Nasıl Çalışır
Laravel’in Kuyruğu sistemi, işi web sürecinden ayırır. Görevi doğrudan çalıştırmak yerine, bir işi bir kuyruk sürücüsüne (bizim durumumuzda Redis) dağıtırsınız ve ayrı bir işçi süreci bunu alır ve arka planda çalıştırır.
// İş sınıfı
// app/Jobs/ReconcileTransactions.php
class ReconcileTransactions implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public int $tries = 3;
public int $backoff = 60; // tekrar denemeler arasındaki saniye sayısı
public function handle(TransactionService $service): void
{
$service->reconcileAll();
}
public function failed(Throwable $exception): void
{
// Slack veya e-posta ile bildirim gönder — asla sessiz başarısızlık yok
Notification::send(
User::admins(),
new ReconciliationFailed($exception->getMessage())
);
}
}
// İşin dağıtılması (zamanlayıcıdan veya manuel olarak)
ReconcileTransactions::dispatch()
->onQueue('critical')
->delay(now()->addSeconds(5));
Bu sistemin sunduğu üç şey:
- Tekrar deneme mantığı — iş başarısız olursa, Laravel bunu $tries kez tekrar deneyebilir
- Başarısızlık yönetimi — final başarısızlıkta failed() metodu devreye girer
- Kuyruk önceliği — ‘critical’ kuyruk, ‘default’ kuyruktan önce işçilere ulaşır
Horizon — Gözlemlenebilirlik Katmanının Eksikliği
Horizon — Gözlemlenebilirlik Katmanının Eksikliği
Laravel Horizon kullanmanın gerçek nedeni görünürlüktür. Bunun olmaması durumunda, işlerin takılıp takılmadığını, ne kadar sürdüğünü veya işçi sayısının yeterli olup olmadığını bilmeden hareket edersiniz.
composer require laravel/horizon
php artisan horizon:install
php artisan horizon
Kurulumdan sonra, Horizon size /horizon adresinde bir kontrol paneli sunar:
- Dakikada işlenen işler (üretkenlik)
- Başarısız olan işler ve istisna izleri
- Gerçek zamanlı kuyruk uzunlukları
- İşçi süreç sayısı ve bellek kullanımı
Yukarıdaki fintech müşterisi için, Horizon hemen uzlaştırma işinin veritabanı bağlantısını toplam 35 saniye boyunca tuttuğunu ortaya çıkardı — bu, cron ile görünmezdi. Bunu 500 satırlık parçalar halinde işleme alarak düzelttik.
// Önce: tüm işlemleri belleğe yükler
$transactions = Transaction::pending()->get();
// Sonra: bellek dostu 500 satırlık parçalarda işler
Transaction::pending()->cursor()->each(function ($transaction) {
$this->reconcileSingle($transaction);
});
Sonuç: maksimum bellek kullanımı 380MB’dan 42MB’a düştü. İş süresi 35 saniyeden 4.2 saniyeye düştü. Artık hiçbir web işçisi zaman aşımına uğramıyor.
Hangi Durumlarda Hala Cron Kullanmalısınız?
Hangi Durumlarda Hala Cron Kullanmalısınız?
Her zamanlanmış görev kuyruk gerektirmez. Cron, aşağıdaki durumlarda uygundur:
- Görev 2 saniyeden kısa sürüyorsa
- Başarısızlık kabul edilebilir ve bildirim gerekmezse
- Tekrar deneme mantığına ihtiyaç yoksa
- Görev tamamen içsel ise (log temizleme, önbellek ısıtma vb.)
Cron aşağıdaki durumlarda yanlış bir seçimdir:
- Dış API çağrıları işleniyorsa (takılabilir)
- Kullanıcı bilgilerinin yönetimi gerektiğinde ve başarısızlığın denetlenmesi gerekiyorsa
- Görev süresi veri hacmine bağlı olarak değişiyorsa
- Zirve yüklerde işçileri ölçeklendirme gerekiyorsa
Üretim Konfigürasyonu — Neleri Kullanırım
Üretim Konfigürasyonu — Neleri Kullanırım
// config/horizon.php — üretime hazır yapılandırma
'environments' => [
'production' => [
'supervisor-1' => [
'maxProcesses' => 10,
'balanceMaxShift' => 1,
'balanceCooldown' => 3,
'queues' => ['critical', 'default', 'low'],
],
],
],
Supervisor, üretimde Horizon sürecini yönetir. Eğer işçi ölürse, Supervisor bunu tekrar başlatır — sıfır manuel müdahale.
; /etc/supervisor/conf.d/horizon.conf
[program:horizon]
process_name=%(program_name)s
command=php /var/www/örnek.com/artisan horizon
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stdout_logfile=/var/log/horizon.log
Cron vs Kuşak — Karar Tablosu
Cron vs Kuşak — Karar Tablosu
| Kriterler | Cron / Zamanlayıcı | Laravel Queue + Redis |
|---|---|---|
| Başarısızlık durumu için tekrar deneme | Hayır | Evet (ayarlanabilir) |
| Web sunucusu üzerindeki etkisi | İşçileri bloke eder | Sıfır etki |
| Başarısızlık bildirim sistemi | Manuel | Yerleşik failed() |
| Gösterge tablosu görünürlüğü | Yok | Horizon kontrol paneli |
| Yatay ölçeklendirme | Mümkün değil | Talep üzerine işçi ekleme |
| Zirve yük yönetimi | Ölçeklendiremiyor | Kuyrukları otomatik dengeleme |
| Uygulama süresi | Dakikalar | 2-4 saat |
Sonuç
Sonuç
Cron görevleri yanlış değildir — basit, düşük riskli zamanlanmış işler için doğru araçtır. Yanlış olan, kullanıcı verilerini, dış API’leri veya değişken süreli işleri etkileyen hiçbir şey için kullanılmalarıdır.
Bu temele dayanan fintech projesi, refaktör aşamasından bu yana 2.3 milyon kuyruk işlemi gerçekleştirmiştir. Başarısızlık oranı: %0.003. Tüm başarısızlıklar bildirilip birkaç dakika içinde çözüme kavuşturulmuştur.
Kaynak: Orijinal Makale


