Yoğun trafik altında bir Laravel uygulaması deploy edip queue'daki job'ların bir anda yok olduğunu izlediyseniz, ne demek istediğimi anlıyorsunuzdur. Basit bir php artisan queue:work süreci ve restart hook'undan oluşan varsayılan kurulum, düşük trafikli uygulamalar için yeterlidir. Ama saatte binlerce job işlemeye başladığınızda, aceleci bir deploy ciddi bir riske dönüşür.

Bu yazıda production'da kullandığım tam kurulumu anlatacağım: queue yönetimi için Laravel Horizon, süreç denetimi için Supervisor ve sıfır kesintili worker yeniden başlatmaları için Envoyer.

Aceleyle Yapılan Restart'ların Sorunu

Deploy sırasında php artisan horizon:terminate çalıştırdığınızda, Horizon tüm worker'lara mevcut job'ı bitirip temiz çıkış yapmaları sinyalini gönderir. Bu iyi bir şey. Sorun, terminate ile Supervisor'ın süreci yeniden başlatması arasındaki boşlukta yatar. O pencerede — yalnızca birkaç saniye bile olsa — job'lar sessizce gecikebilir ya da --stop-when-empty yanlış kullanılmışsa tamamen kaybolabilir.

Temel nokta: Amaç worker'ları anında yeniden başlatmak değil; hiçbir job'ın eski kod üzerinde çalışmaya başlamamasını ve uçuştaki hiçbir job'ın yarıda bırakılmamasını sağlamaktır.

Supervisor Yapılandırması

Sağlam bir Supervisor konfigürasyonu ile başlayın. Buradaki stopwaitsecs değeri kritiktir — en uzun süren job'ınızdan uzun olmalıdır; aksi takdirde Supervisor çalışan bir worker'ı SIGKILL ile öldürür.

[program:horizon]
process_name=%(program_name)s
command=php /var/www/html/artisan horizon
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stdout_logfile=/var/www/html/storage/logs/horizon.log
stopwaitsecs=3600
stopsignal=SIGTERM

Envoyer Deployment Hook'u

Envoyer projenizde, Horizon'a temiz çıkış sinyali gönderen bir After Activate hook'u ekleyin. Yeni release zaten yerli yerinde olduğundan, Supervisor Horizon'ı yeniden başlattığında güncel kodu otomatik olarak alır.

php {{ release }}/artisan horizon:terminate

Hook'un tamamı bu kadar. Sıralama önemlidir: Envoyer önce yeni release'i aktif eder (sembolik bağlantı değiştirme), ardından eski worker'lara terminate sinyali gönderir. Eski release üzerinde çalışan worker'lar job'larını temiz bitirir. Yeni worker'lar yeni kod ile başlar.

Geçişi İzleme

Deploy sırasında Horizon panonuzdaki Processes sekmesini takip edin. Worker'lar job'larını bitirdikçe eski süreç sayısının düştüğünü, Supervisor yeniden başlattıkça yeni süreç sayısının yükseldiğini görmelisiniz. Toplam işleme kapasitesi anlık olarak düşer ama hiç sıfıra ulaşmaz.

Doğrulama kontrol listesi

  • Deploy penceresi boyunca başarısız job yok
  • Supervisor log'u temiz SIGTERM ve restart dizisini gösteriyor
  • 60 saniye sonra Horizon panosu doğru worker sayısını gösteriyor
  • Eski release üzerinde çalışan "eski" worker süreci yok

Bu kurulum, yüksek hacimli birçok Laravel uygulamasında kendini kanıtladı. Gerçek sıfır kesintili queue deploy için ihtiyacınız olan tek şey 60 satırlık bir Supervisor konfigürasyonu ve tek bir Envoyer hook'u.