# Laravel Queue ve Supervisor ile Asenkron İşlemler

> Laravel'de Queue ve Supervisor ile asenkron iş kuyruğu kurulumu ve arka plan işlemleri.

- Yayın: 2023-07-02
- Güncelleme: 2026-09-07
- Kategori: Framework & Kütüphane
- Etiketler: PHP, Laravel
- Okuma süresi: 3 dk okuma
- Kaynak: https://www.muhammetsafak.com.tr/blog/laravel-queue-ve-supervisor-ile-asenkron-islemler/
- Dil: tr-TR
- Yazar: Muhammet Şafak

---
Bir web isteğinin tek bir görevi vardır: kullanıcıya hızlı yanıt dönmek. Ama bazı işler hızlı değildir — e-posta göndermek, bir görseli işlemek, üçüncü parti bir API'yi beklemek. Bu işleri istek-yanıt döngüsünün içinde yaparsanız, kullanıcı sizin yavaş işinizi bekler. Laravel Queue tam burada devreye giriyor: işi şimdi sıraya koy, yanıtı hemen dön, asıl işi arka planda yap.

Bu yazıda Laravel'de bir iş kuyruğunu nasıl kurduğumu ve onu production'da ayakta tutmak için Supervisor'ı nasıl kullandığımı anlatıyorum.

## Kuyruk sürücüsü seçimi

Laravel Queue; veritabanı, Redis, Amazon SQS gibi farklı sürücülerle çalışır. Sürücü, sıraya alınan işlerin nerede saklanacağını belirler. `.env` dosyasındaki `QUEUE_CONNECTION` değeri bunu kontrol eder ve [Laravel 10.x Queue dokümanının belirttiği gibi](https://laravel.com/docs/10.x/queues#connections-vs-queues) yeni uygulamalarda varsayılan sürücü `sync`'tir — yani iş hiç sıraya alınmaz, anında çalışır. Geliştirme sırasında pratiktir; ama production'da gerçek bir sürücüye geçmeden Queue'nun hiçbir faydasını görmezsiniz.

Bu yazıda veritabanı sürücüsünü kullanıyorum. Küçük ve orta yükte yeterli, ek bir altyapı gerektirmiyor. İşler `jobs` tablosunda saklanır; [dokümanın tarif ettiği gibi](https://laravel.com/docs/10.x/queues#database) tabloyu oluşturmak için:

```bash
php artisan queue:table
php artisan migrate
```

## Bir iş tanımlamak

Kuyruğa atılacak her iş bir sınıftır. Örnek olarak arka planda e-posta gönderen bir `SendMailJob` oluşturuyorum:

```bash
php artisan make:job SendMailJob
```

Üretilen sınıfı, alacağı parametreleri ve yapacağı işi netleştirerek dolduruyorum:

```php
<?php
namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class SendMailJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(
        private string $name,
        private string $mail,
    ) {}

    public function handle(): void
    {
        $subject = 'Merhaba ' . $this->name;
        $msg = 'Sitemize üye olduğunuz için teşekkür ederiz!';
        if (!mail($this->mail, $subject, $msg)) {
            throw new \Exception('Mail gönderilemedi.');
        }
    }
}
```

İki nokta önemli. Birincisi: `__construct` ile aldığım veriyi [sınıfın özelliklerinde](/blog/php-7-4-ile-gelen-typed-properties-ve-ok-fonksiyonlari/) saklıyorum — Laravel bu veriyi serialize edip kuyrukta tutuyor, iş çalışınca geri yüklüyor. Bu yüzden constructor'a koca nesneler değil, sade değerler (id'ler, kısa string'ler) vermek iyi bir alışkanlıktır. İkincisi: `handle` içinde işin başarısız olduğu durumda bir exception fırlatıyorum. Bu isteğe bağlı değil. [Doküman şöyle diyor](https://laravel.com/docs/10.x/queues#dealing-with-failed-jobs): iş işlenirken bir exception fırlarsa, iş otomatik olarak kuyruğa geri bırakılır ve izin verilen deneme sayısına ulaşana kadar tekrar denenir. İşi kuyruğa elle geri bırakmanın bir yolu daha var — `release()` — ama sessizce `return` eden bir job ikisini de yapmaz: kuyruk onu bitmiş kabul eder, başarısız olduğunda bile başarılı sayılır.

İşi kuyruğa atmak tek satır:

```php
\App\Jobs\SendMailJob::dispatch('Muhammet', 'info@muhammetsafak.com.tr');
```

## İşleri yürütmek

Kuyruğa atılan işler kendiliğinden çalışmaz; onları işleyen bir worker gerekir:

```bash
php artisan queue:work
```

Bu komut kuyruğu sürekli dinler ve yeni iş geldikçe işler. Farklı öncelikteki işleri ayırmak isterseniz `onQueue()` ile adlandırılmış kuyruklar kullanabilir, worker'ı da o kuyruğa yönlendirebilirsiniz:

```php
\App\Jobs\SendMailJob::dispatch($name, $mail)->onQueue('medium');
```

```bash
php artisan queue:work --queue=high,medium,default
```

Buradaki sıralama önceliği belirler: [doküman bunu açıkça söylüyor](https://laravel.com/docs/10.x/queues#queue-priorities) — `high` kuyruğundaki işlerin tamamı işlenmeden `medium`'a geçilmez.

## Supervisor: worker'ı ayakta tutmak

`queue:work` uzun ömürlü bir süreçtir — ve uzun ömürlü süreçler ölür. Bir hata, bir bellek sınırı, bir deploy… worker durur ve kimse fark etmezse kuyruk sessizce birikir. Production'da bu kabul edilemez.

Supervisor, Unix sistemlerde arka plan süreçlerini izleyen ve durduklarında onları yeniden başlatan bir araçtır. Laravel worker'ları için tam da bunu istiyorum.

```bash
sudo apt-get update
sudo apt-get install supervisor -y
```

`/etc/supervisor/conf.d/` altına bir yapılandırma dosyası açıyorum:

```ini
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /proje/yolu/artisan queue:work --queue=default --tries=3
autostart=true
autorestart=true
user=deploy
numprocs=8
redirect_stderr=true
stdout_logfile=/proje/yolu/storage/logs/worker.log
stopwaitsecs=3600
```

Birkaç satır kritik. `autorestart=true`, worker öldüğünde onu geri getirir. `numprocs=8` sekiz paralel worker çalıştırır — bu sayıyı yükünüze göre ayarlayın. `stopwaitsecs=3600`, deploy sırasında çalışan bir işin yarıda kesilmemesi için ona bitmesi adına süre tanır: [Supervisor dokümanına göre](https://supervisord.org/configuration.html#program-x-section-settings) bu değer, sürece durdurma sinyali gönderildikten sonra kapanmasını beklemek için tanınan saniye sayısıdır ve varsayılanı 10'dur — bir saatlik bir işi on saniyede öldürürsünüz. [Laravel'in kendi örnek yapılandırması](https://laravel.com/docs/10.x/queues#supervisor-configuration) da aynı sebeple 3600 kullanıyor. Yapılandırmayı tanıtıp başlatmak için:

```bash
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-worker:*
```

## Son bir not

Kod değiştirip deploy ettiğinizde, çalışan worker'lar eski kodu bellekte tutmaya devam eder. [Doküman bunu ayrı bir başlık altında uyarıyor](https://laravel.com/docs/10.x/queues#queue-workers-and-deployment): worker'lar uzun ömürlü süreçler olduğu için yeniden başlatılmadıkça kodunuzdaki değişiklikleri fark etmezler. Her deploy'dan sonra `php artisan queue:restart` çalıştırmayı dağıtım adımlarınıza ekleyin — yoksa "kodu güncelledim ama hâlâ eski davranıyor" diye saatlerce uğraşırsınız. Bunu birkaç kez yaşadıktan sonra öğrendim.

Laravel Queue ve Supervisor birlikte, basit ama sağlam bir asenkron işleme katmanı veriyor: Laravel işi tanımlar ve sıraya koyar, Supervisor da o işi yapan süreçlerin hiç durmamasını sağlar. İkisi de tek başına eksik; değer, birlikte çalışmalarında.

---

### Kaynaklar

- [Laravel 10.x: Queues](https://laravel.com/docs/10.x/queues)
- [Laravel 10.x: Queues — Dealing With Failed Jobs](https://laravel.com/docs/10.x/queues#dealing-with-failed-jobs)
- [Laravel 10.x: Queues — Supervisor Configuration](https://laravel.com/docs/10.x/queues#supervisor-configuration)
- [Laravel 10.x: Queues — Queue Workers & Deployment](https://laravel.com/docs/10.x/queues#queue-workers-and-deployment)
- [Supervisor: [program:x] Section Settings](https://supervisord.org/configuration.html#program-x-section-settings)
