İçindekiler
- 1 Laravel Horizon ve Queue İşleri İçin Kaynak Planlama Neden Ayrı Ele Alınmalı?
- 2 Ön Hazırlık: Queue İşlerinizi Doğru Tanımlamak
- 3 CPU Planlama: Kaç vCPU ve Kaç Worker?
- 4 RAM Planlama: Worker Başına Bellek Hesabı
- 5 Redis Planlama: Bellek, Kalıcılık ve Kuyruk Derinliği
- 6 Queue Yapısı ve Worker Dağılımını Tasarlamak
- 7 Örnek Senaryolar: Küçük SaaS’tan Orta Ölçekli E-ticarete
- 8 Adım Adım Uygulanabilir Plan: Kendi Projende Nasıl İlerlemelisin?
- 9 Sonuç: Laravel Horizon İçin Kaynak Planlama Bir Kerelik Değil, Sürekli Bir Süreç
Laravel Horizon ve Queue İşleri İçin Kaynak Planlama Neden Ayrı Ele Alınmalı?
Laravel ile ciddi bir proje geliştirdiğiniz anda, arka planda çalışan kuyruk (queue) işleri kaçınılmaz hale geliyor: e-posta gönderimleri, bildirimler, raporlar, dış API entegrasyonları, medya işleme, fatura oluşturma, PDF üretimi ve daha fazlası. Bu noktada Laravel Horizon, hem kuyruk işçilerini (worker) yönetmek hem de metrikleri izlemek için müthiş bir arayüz sunuyor; ancak performansın gerçekten iyi olması için VPS kaynak planlamasını doğru yapmanız gerekiyor.
Birçok ekibin yaşadığı ortak sorun şu: Web istekleri için CPU/RAM planlaması yapılmış, fakat Horizon ve queue işleri için aynı sunucu, aynı kaynaklar ve rastgele bir worker sayısı kullanılıyor. Sonuçysa tanıdık: Web tarafında zaman zaman 502/504 hataları, cron görevlerinin gecikmesi, birikmiş kuyruklar ve bazen de Redis veya PHP süreçlerinin OOM (Out of Memory) sebebiyle öldürülmesi.
Bu yazıda DCHost ekibi olarak, Laravel Horizon ve queue işlerinizi VPS üzerinde nasıl boyutlandırmanız gerektiğini adım adım ele alacağız. CPU, RAM, Redis ve worker sayısını sadece sezgiyle değil, ölçülebilir metrikler ve basit formüller üzerinden planlayacağız. Küçük bir SaaS, orta ölçekli bir e-ticaret veya yüksek trafikli bir Laravel uygulaması için örnek senaryolarla, kendi projenize uyarlayabileceğiniz pratik bir rehber çıkaracağız.
Ön Hazırlık: Queue İşlerinizi Doğru Tanımlamak
Worker sayısını veya Redis belleğini hesaplamadan önce, aslında şu soruyu netleştirmeniz gerekiyor: Queue işleriniz ne yapıyor? Tüm işler aynı tip değil ve kaynak tüketimleri çok farklı.
1) İş Tiplerini Sınıflandırın: CPU-bound, IO-bound, Karma
Genelde queue işleri üç kategoriye ayrılır:
- CPU-bound işler: Görsel yeniden boyutlama, yoğun veri işleme, karmaşık hesaplamalar, PDF render vb. CPU çekirdeğini uzun süre meşgul eder.
- IO-bound işler: E-posta gönderimi, üçüncü parti API çağrıları, dosya upload/download, yavaş disk erişimi gibi, bekleme (I/O) süresi yüksek, CPU kullanımı görece düşük işler.
- Karma işler: Hem CPU hem IO kullanan, örneğin rapor oluştururken veritabanından çok sayıda kayıt çekip, bunları işleyen ve sonunda dosya üreten işler.
Planlama yaparken bu ayrım kritik, çünkü CPU-bound işler için worker sayısını düşük, IO-bound işler için ise daha yüksek tutabilirsiniz.
2) Ortalama İş Süresini ve Hacmini Ölçün
Horizon, her job için çalıştırma süresi ve başarısızlık oranı gibi metrikler sunar. Bunları temel alarak kaba bir kapasite hesabı yapabilirsiniz:
- Ortalama iş süresi (t): Örneğin e-posta gönderimi için 200 ms, PDF üretimi için 5 sn gibi.
- Saatlik iş hacmi (N): Zirve saatlerde kuyrukta bekleyecek iş sayısı, örneğin promosyon kampanyasında saatte 10.000 bildirim.
Bu iki değeri bilmek, sizin için en kritik hesap olan gerekli toplam işçi kapasitesini çıkarırken işimizi çok kolaylaştırır. Eğer henüz Horizon kullanmıyor veya metrik toplamıyorsanız, en azından birkaç gün boyunca loglayarak iş sürelerini ölçmenizi tavsiye ederim.
Laravel prod ortamını genel olarak optimize etmeye dair daha geniş bir bakış isterseniz, Laravel prod ortam optimizasyonu rehberimizi mutlaka okumanızı öneririm.
CPU Planlama: Kaç vCPU ve Kaç Worker?
CPU planlaması, özellikle Horizon supervisor tanımlarınızda kaç worker açacağınızı belirlerken temel alınması gereken kısım. Yanlış planlama yaptığınızda, ya CPU’yu boğar, web isteklerini yavaşlatırsınız ya da gereksiz az worker ile kuyrukların şişmesine sebep olursunuz.
CPU-bağımlı İşler İçin Worker Sayısı
CPU-bound işler için genel kural şudur:
- Worker sayısı ≈ vCPU sayısı (veya en fazla vCPU + 1)
Örneğin 4 vCPU’lu bir VPS’te yoğun görüntü işleme yapan bir kuyruk varsa, bu kuyruk için 3–4 worker’dan fazlasını açmak çoğu zaman zarardan başka bir şey getirmez. Çünkü hepsi CPU’yu sonuna kadar kullanmaya çalışacak ve context-switch maliyetleri artacaktır.
Basit bir formülle düşünelim:
- İş başına ortalama süre: t = 5 sn
- vCPU sayısı: C = 4
- Worker sayısı: W ≈ C = 4
Bu durumda teorik maksimum throughput yaklaşık: 4 worker × (60 / 5) = saniyede 0,8 iş, yani dakikada 48 iş, saatte 2.880 iş olur. Zirve saatte 2.000 rapor üretiyorsanız, bu yapı yeterlidir; 20.000 rapor üretmek istiyorsanız ya iş süresini kısaltmanız ya da CPU’yu büyütmeniz gerekir.
IO-bağımlı İşler İçin Worker Sayısı
IO-bound işler CPU’yu çok az kullanır, çoğu zamanı bekleyerek geçirir. Örneğin harici bir e-posta servisine istek atarken veya yavaş bir API’yi beklerken CPU boştadır; bu yüzden aynı CPU üzerinde daha fazla worker koşturabilirsiniz.
Pratikte sık kullandığımız aralık:
- Worker sayısı ≈ vCPU × (2 – 4)
Örnek:
- Ortalama iş süresi: t = 0,2 sn (e-posta kuyruğu)
- vCPU sayısı: C = 2
- Worker sayısı: W = 6 (3 × vCPU)
Bu durumda teorik throughput: 6 × (60 / 0,2) = dakikada 1.800 iş, saatte 108.000 iş. E-posta gibi hafif işler için oldukça tatmin edici.
Karma İşler İçin Worker Sayısı
Karma tipte işler (hem veritabanı okuyor hem hesaplama yapıyor) için ne çok agresif ne de çok muhafazakâr bir yaklaşım gerekiyor. Genelde:
- Worker sayısı ≈ vCPU × 1,5 – 2
4 vCPU’lu bir VPS’te karma işlerin koşturulduğu kuyruk için 6–8 worker çoğu projede makul bir başlangıç noktasıdır.
Horizon Supervisor Ayarlarını Bu Mantığa Göre Tasarlayın
Horizon’da config/horizon.php dosyasında supervisor tanımlarken, her supervisor’a özel processes (worker sayısı), queue listesi ve balancing stratejisi verebilirsiniz:
- processes: Yukarıdaki CPU/IO hesaplarına göre belirleyin.
- connection/queue: Ağır işleri ayrı kuyruklara bölün (ör.
high,default,emails,reports). - balance:
simpleveyaautoile kuyruklar arasında işçi dağılımını optimize edin.
Horizon ve supervisor yönetimine genel bir girişe ihtiyacınız varsa, VPS üzerinde arka plan işleri ve kuyruk yönetimi rehberimiz başlangıç için oldukça faydalı olacaktır.
RAM Planlama: Worker Başına Bellek Hesabı
CPU planlaması kadar kritik ikinci konu da RAM kullanımı. Laravel worker’ları PHP CLI süreçleri olduğu için her biri belirli miktarda bellek kullanır. Yanlış hesaplanmış bir worker sayısı veya bellek limiti, Redis ve PHP süreçlerinin OOM Killer tarafından öldürülmesine yol açabilir.
Worker Başına Ortalama Bellek Kullanımı
Worker başına RAM tüketimi, uygulamanızın boyutuna, kullanılan paketlere ve job’ların ne yaptığına göre değişir. Pratikte sık gördüğümüz aralıklar:
- Küçük projeler: 40–80 MB / worker
- Orta projeler: 80–150 MB / worker
- Ağır projeler (büyük ORM modelleri, raporlama): 150–300 MB / worker
Bunu kendi VPS’inizde htop veya top ile rahatlıkla ölçebilirsiniz. Birkaç worker ile yük altında test yapıp, her bir php artisan queue:work sürecinin RSS değerine bakın.
Toplam RAM İhtiyacı için Basit Formül
Toplam RAM ihtiyacını kabaca şöyle hesaplayabilirsiniz:
- OS + servisler (Nginx, systemd, ufw vs.): ~300–500 MB
- PHP-FPM / web işlemleri: 500–1500 MB (trafiğe ve FPM ayarlarına göre)
- Redis: 100–1024 MB (kuyruk ve cache yüküne göre)
- Horizon worker’ları: Worker_sayısı × Worker_RAM
- Güvenlik tamponu: Toplamın %20–30’u
Örneğin:
- OS: 500 MB
- PHP-FPM: 1000 MB
- Redis: 512 MB
- Worker sayısı: 10
- Worker başı RAM: 100 MB
Toplam ≈ 500 + 1000 + 512 + (10 × 100) = 3.012 MB. Güvenlik payı ile birlikte 3.012 × 1,3 ≈ 3,9 GB. Yani burada 4 GB RAM’li bir VPS, alt sınırda ama kabul edilebilir; 8 GB ise sizi çok daha rahatlatır.
RAM sınırlarında çalışırken swap, OOM Killer ve bellek baskısı konularını iyi anlamak için, VPS’te RAM, swap ve OOM Killer yönetimi yazımıza da mutlaka göz atın.
memory_limit ve max_execution_time Ayarlarının Etkisi
PHP’nin memory_limit ve max_execution_time ayarları, queue worker’larının davranışını doğrudan etkiler:
- memory_limit: Çok düşükse job’lar
Allowed memory size exhaustedhatasıyla patlar; çok yüksekse de birkaç job belleği şişirip tüm sunucuyu kilitleyebilir. - max_execution_time: CLI için genelde
0(sınırsız) kullanılır; ancak job bazındatimeoutayarıyla yine de sınır getirebilirsiniz.
Genelde worker’lar için 256–512 MB aralığı makul bir başlangıçtır. PHP ayarlarını sistematik bir şekilde ele almak isterseniz, PHP ayarları rehberimiz sizin için iyi bir referans olacaktır.
Redis Planlama: Bellek, Kalıcılık ve Kuyruk Derinliği
Laravel Horizon ile birlikte genellikle Redis queue driver kullanıyoruz. Redis hem kuyruk verisini hem de bazen cache/session verilerini taşıdığı için, kapasite planlamasında ayrı bir başlık açmak gerekiyor.
Kuyruk Derinliği ve Job Boyutu
Redis tarafında RAM ihtiyacını kabaca şu formülle düşünebilirsiniz:
- Toplam kuyruk RAM ≈ Ortalama job boyutu × Maksimum kuyruk derinliği × 1,5
Buradaki 1,5 çarpanı, Redis’in key yapıları ve ek metadatalar için kabaca bir overhead faktörüdür.
Örnek:
- Ortalama job payload boyutu: 1 KB
- Maksimum kuyruk derinliği: 100.000 job
Toplam ≈ 1 KB × 100.000 × 1,5 = 150 MB. Aynı Redis içinde cache ve session da tutuyorsanız, örneğin 300–400 MB da onlara ayırmanız gerekebilir. Bu durumda Redis için en az 512–768 MB RAM planlamak mantıklı olur.
maxmemory ve Eviction Politikaları
Redis’te maxmemory ayarı ile üst bellek sınırını belirleyebilir, maxmemory-policy ile de hangi key’lerin atılacağını tanımlayabilirsiniz. Kuyruk verisinin kaybolmasını istemiyorsanız, genelde:
- Kuyruk için ayrı bir Redis instance’ı kullanmak
- Bu instance’ta evicton politikasını çok dikkatli seçmek (veya hiç eviction olmamasını sağlamak)
en sağlıklı yoldur. Cache verisi kaybolabilir, yeniden oluşturulur; ama kuyruktaki işlerin kaybolması genellikle kabul edilemez.
Redis’i genel olarak hosting performansı açısından daha derin anlamak için, Redis cache nedir ve hosting performansını nasıl artırır yazımızı da inceleyebilirsiniz.
Persistens (AOF/RDB) ve Disk Etkisi
Redis’te kalıcılık için:
- RDB snapshot: Belirli aralıklarla tüm verinin diske dump edilmesi.
- AOF: Her yazma işleminin append-only log’a eklenmesi.
Yüksek hacimli kuyruklarınız varsa, AOF dosyası çok hızlı büyüyebilir. NVMe diskli bir DCHost VPS üzerinde bu yük genellikle yönetilebilir olsa da, disk I/O baskısını izlemek ve gerektiğinde AOF yeniden yazma (rewrite) politikalarını gözden geçirmek gerekir.
Queue Yapısı ve Worker Dağılımını Tasarlamak
CPU, RAM ve Redis için kabaca bir plan çıkardıktan sonra, işin mimari boyutuna geliyoruz: Kaç kuyruk, hangi iş için kaç worker?
Queue’ları İş Tipine Göre Ayırın
Tek bir default kuyruğuna her şeyi atmak, en sık gördüğümüz anti-pattern’lerden biri. Bunun yerine:
- high: Kullanıcıyı doğrudan etkileyen hızlı işler (e-posta onayı, kritik bildirimler).
- default: Normal öneme sahip arka plan işler.
- emails: Toplu e-posta ve bülten gönderimi.
- reports: Ağır raporlar, dış sistemlerle toplu senkronizasyon.
- low: Gecikmeye daha toleranslı işler (log işleme, analitik vb.).
Bu ayrım, Horizon supervisor’lar aracılığıyla her kuyruğa farklı sayıda worker ve farklı kaynak önceliği tanımlamanızı sağlar.
Supervisor Bazında Worker Planı Örneği
Diyelim ki 4 vCPU, 8 GB RAM’li bir VPS’iniz var. Çoğu orta ölçekli Laravel projesi için mantıklı bir başlangıç yapısı şöyle olabilir:
- Supervisor: high
queues:high,default
processes: 4 (önemli işler için daha garantili CPU) - Supervisor: emails
queues:emails
processes: 4–6 (IO-bound olduğu için daha fazla worker) - Supervisor: reports
queues:reports
processes: 2–3 (CPU-bound, raporlar daha ağır)
Böylece toplam 10–13 worker’a ulaşırsınız. Daha önce hesapladığımız RAM ve CPU limitlerine uyduğunuz sürece bu yapı genellikle dengeli çalışır. Zamanla Horizon istatistiklerini izleyerek, özellikle bekleme sürelerine ve iş başarısızlık oranlarına bakarak worker sayılarını yukarı/aşağı çekebilirsiniz.
Job Timeout, maxAttempts ve Hatalı İşleri Yönetmek
Yüksek concurrency her zaman iyi değildir; hatalı job’lar hızla üst üste patlayabilir ve hem Redis’i hem de uygulamanızı zorlayabilir. Her job için:
- timeout: Örneğin ağır rapor için 120–300 sn, e-posta için 30 sn gibi.
- maxAttempts: Kritik işlerde 3–5, idempotent işlerde biraz daha yüksek.
- failOnTimeout: Zaman aşımı durumunda job’un başarısız sayılmasını sağlayın.
Horizon’un failed jobs ekranını düzenli takip ederek, özellikle belirli tip job’ların sürekli tekrar kuyruğa atılmasını ve gereksiz kaynak tüketmesini önleyebilirsiniz.
Örnek Senaryolar: Küçük SaaS’tan Orta Ölçekli E-ticarete
Teoriyi pratiğe dökmek en iyi, somut senaryolarla mümkün. DCHost tarafında sık gördüğümüz üç tip projeye göre örnek VPS ve Horizon konfigürasyonu üzerinden gidelim.
Senaryo 1: Küçük SaaS (2 vCPU, 4 GB RAM)
Özellikler:
- Günlük 10–20 bin sayfa görüntüleme
- Kuyrukta çoğunlukla e-posta ve basit bildirim işleri
- Nadiren rapor üretimi
Önerilen VPS kaynakları (örnek):
- 2 vCPU, 4 GB RAM, NVMe diskli DCHost VPS
- Redis ve web uygulaması aynı VPS üzerinde (ama ileride ayrılmaya hazır mimari)
Önerilen Horizon yapısı:
- Supervisor: high-default
queues:high,default
processes: 2 (CPU-bound olabilecek küçük işler için) - Supervisor: emails
queues:emails
processes: 3–4 (IO-bound)
Worker bellek tüketimi ortalama 70 MB ise, toplam worker RAM tüketimi ≈ 5–6 worker × 70 MB ≈ 350–420 MB. Geri kalan bellek PHP-FPM, Redis ve OS için yeterlidir. Burada en kritik nokta, peak saatlerde e-posta kuyruğunun çok birikmediğini gözlemlemek ve gerektiğinde emails supervisor’ına geçici olarak daha fazla worker vermektir.
Senaryo 2: Orta Ölçekli E-ticaret (4 vCPU, 8 GB RAM)
Özellikler:
- Günlük 50–200 bin sayfa görüntüleme
- Sipariş sonrası e-posta, stok senkronizasyonu, fatura PDF üretimi
- Dış ERP/CRM sistemleriyle zamanlanmış senkronizasyonlar
Önerilen VPS kaynakları (örnek):
- 4 vCPU, 8 GB RAM, NVMe disk
- İleride veritabanını ayrı sunucuya taşıyabilecek mimari
Önerilen Horizon yapısı:
- Supervisor: high
queues:high,default
processes: 4 - Supervisor: emails
queues:emails
processes: 4–6 - Supervisor: reports
queues:reports
processes: 2–3 (CPU-bound)
Burada toplam 10–13 worker’dan bahsediyoruz. Worker başına 120 MB bellek varsayalım: 13 × 120 MB ≈ 1,56 GB. OS (~500 MB), PHP-FPM (~1500 MB), Redis (~600 MB) ve güvenlik tamponu ile birlikte 8 GB’lık bir VPS gayet konforlu bir alan sunar.
Bu tip projelerde hem web trafiği hem de arka plan işleri ciddi boyuta ulaştığından, Laravel için doğru VPS kaynaklarını seçme rehberi ve PHP-FPM ayarları hesaplama yazısı da pratikte çok işinize yarar.
Senaryo 3: Yüksek Trafikli Laravel Uygulaması
Özellikler:
- Günlük 500k+ sayfa görüntüleme
- Ağır analitik, raporlama, video/görsel işleme, çoklu entegrasyon
- Onlarca farklı job tipi ve karmaşık queue mimarisi
Bu seviyede genellikle yaklaşım değişiyor:
- Web istekleri için ayrı bir veya birkaç VPS/dedicated sunucu
- Queue/Horizon için ayrı bir veya birkaç VPS/dedicated sunucu
- Redis ve veritabanı için yine ayrı sunucular
Örneğin sadece queue işleri için 8–16 vCPU, 16–32 GB RAM aralığında bir DCHost VPS veya dedicated sunucu, üzerinde:
- CPU-bound ağır raporlar için 8–12 worker
- IO-bound bildirim/e-posta işleri için 40–60 worker
- Her bir iş tipi için ayrı supervisor ve ayrı timeout/attempt politikaları
şeklinde bir yapı planlanabilir. Bu noktada mutlaka load test (k6, JMeter vs.) ve sürekli izleme (Prometheus, Netdata) ile adım adım büyümek gerekir. Bu tip gelişmiş izleme senaryolarına başlangıç için, VPS izleme ve uyarı kurulum rehberimiz ve VPS kaynak kullanımı izleme rehberi iyi bir referanstır.
Adım Adım Uygulanabilir Plan: Kendi Projende Nasıl İlerlemelisin?
Özetle, Laravel Horizon ve queue işleri için VPS boyutlandırma sürecini şu adımlarla yönetebilirsiniz:
- İş tiplerini sınıflandır: CPU-bound, IO-bound, karma job’ları tespit et.
- İş sürelerini ölç: Horizon metrikleriyle her job için ortalama süreyi (t) çıkar.
- Saatlik hacmi belirle: Zirve saatlerde beklenen job sayısını (N) tahmin et veya ölç.
- Gerekli worker kapasitesini hesapla: Basitçe N / (60 × 60 / t) ile çalışan thread ihtiyacını gör; CPU-bound için W ≈ vCPU, IO-bound için W ≈ vCPU × (2–4) mantığıyla çarpıştır.
- Worker başına RAM’i ölç: Küçük bir test ortamında iş yükü sırasında tek worker’ın RAM kullanımını htop/top ile gözle.
- Toplam RAM hesabını yap: OS + PHP-FPM + Redis + (W × Worker_RAM) + %20–30 buffer şeklinde.
- Supervisor yapılandır:
config/horizon.phpiçinde kuyruklara göre supervisor’lar ve processes değerlerini tanımla. - İzle ve düzelt: İlk hafta Horizon dashboard, Sunucu load, RAM, Redis kullanımını sürekli izleyip, worker sayılarını küçük adımlarla optimize et.
Bu süreci doğru kurduğunuzda, kuyruklarınız hem daha hızlı boşalır hem de web isteklerinizin performansı bozulmaz. DCHost tarafında biz de müşterilerimize tam olarak bu adımlar üzerinden giderek kaynak planlama danışmanlığı veriyoruz.
Sonuç: Laravel Horizon İçin Kaynak Planlama Bir Kerelik Değil, Sürekli Bir Süreç
Laravel Horizon ve queue işleri için VPS kaynak planlama, “bir kere ayarladım, artık unuturum” diyebileceğiniz bir konu değil. Trafiğiniz artıyor, yeni iş tipleri ekleniyor, Redis’e ekstra cache yapıları taşınıyor, raporlar ağırlaşıyor; kısacası zamanla iş yükünüz evrim geçiriyor. Gerçekçi yaklaşım, ölç – planla – uygula – yeniden ölç döngüsünü kurmak.
Bu yazıda CPU, RAM, Redis ve worker sayısını formüllerle ve gerçekçi varsayımlarla nasıl hesaplayabileceğinizi, küçük SaaS’tan orta ölçekli e-ticarete kadar farklı senaryolarda ne tür konfigürasyonlar kullanabileceğinizi birlikte gördük. Artık yeni bir DCHost VPS paketi seçerken veya mevcut sunucunuzu yükseltirken, “kaç vCPU, kaç GB RAM, kaç worker?” sorularına sezgiyle değil, net metrikler ve basit hesaplarla cevap verebilirsiniz.
Eğer Laravel tabanlı projeniz büyüyor ve Horizon/queue katmanında zaman zaman kuyruk birikmeleri, geç gelen e-postalar, CPU/RAM patlamaları görüyorsanız, DCHost ekibi olarak hem doğru VPS veya dedicated paketini seçmenizde hem de Horizon mimarinizi gözden geçirmenizde yardımcı olabiliriz. Projenizin trafik ve job metriklerini birlikte analiz edip, bir kapasite planlama tablosu çıkaralım; siz de geliştirmeye odaklanın, altyapı tarafını bize bırakın.
