L
Laravel • Literally Web ID

Arsitektur Event-Driven di Laravel Menggunakan Redis Queue dan Supervisor

⏱️ 15 menit baca • 📅 13 Oct 2026 • 👁️ 1 views
Arsitektur Event-Driven di Laravel Menggunakan Redis Queue dan Supervisor

1. Konteks Industri & Analisis Akar Masalah

Dalam lanskap pengembangan web modern, aplikasi enterprise dituntut untuk merespons permintaan klien (HTTP Request) dalam hitungan milidetik. Namun, kenyataannya, alur bisnis inti sering kali melibatkan operasi yang sangat membebani sumber daya server, seperti mengirimkan email transaksional massal melalui SMTP relay, menghasilkan laporan PDF berukuran besar, memproses pembayaran via gateway pihak ketiga, atau berinteraksi dengan API eksternal yang lambat.

Secara tradisional, pengembang pemula sering kali mengeksekusi tugas-tugas berat ini secara synchronous di dalam siklus hidup permintaan HTTP utama (request-response cycle). Akibatnya, pengguna harus menunggu hingga proses selesai sebelum halaman termuat sepenuhnya. Pendekatan ini menciptakan efek riak negatif pada infrastruktur web:

  • Lonjakan Latensi: Waktu muat halaman melonjak dari rata-rata 150ms menjadi lebih dari 5.000ms.
  • Kelelahan Sumber Daya Web Server: Proses PHP-FPM terikat terlalu lama, menghabiskan koneksi worker pool Nginx/Apache, dan menyebabkan gateway timeout (504 Gateway Time-out).
  • Kegagalan Total (Cascading Failures): Ketika lonjakan traffic terjadi (misalnya saat flash sale), database MySQL dan PHP-FPM kehabisan koneksi, melumpuhkan seluruh aplikasi.

Kondisi Sebelum vs Sesudah Penerapan Arsitektur Event-Driven

Parameter Sebelum (Synchronous / Blocking) Sesudah (Event-Driven + Redis + Supervisor)
Waktu Respon HTTP 3,000ms - 10,000ms+ 80ms - 200ms (Sangat Cepat)
Kapasitas Throughput Rendah (~20 request/detik per server) Tinggi (Ribuan request/detik)
Tingkat Kegagalan Tugas Tinggi (Koneksi terputus = tugas hilang) Rendah (Gagal dieksekusi masuk ke tabel failed_jobs untuk di-retry)
Utilisasi CPU & RAM Tidak stabil, sering spike ekstrem Stabil, terkontrol, dan dapat diprediksi

2. Konsep Inti & Deep Dive Arsitektur

Arsitektur Event-Driven (EDA) di Laravel memisahkan pemicu kejadian (Event) dengan tindakan yang merespon kejadian tersebut (Listener atau Job). Ketika sebuah event terjadi di aplikasi, event tersebut dipetakan ke dalam antrean (Queue), yang kemudian disimpan di dalam in-memory data store berkecepatan tinggi, yaitu Redis.

[ HTTP Request ] ---> [ Laravel Controller ] ---> Dispatches Job
                                                         |
                                                         v
[ Client / Browser ] <--- [ HTTP Response (Fast) ] <--- [ Redis Queue Engine ]
                                                                 |
                                                                 v
[ MySQL Database ] <--- [ Supervisor Daemon ] <--- [ Laravel Queue Worker ]

Under the Hood: Alur Data dan Eksekusi

  1. Dispatch: Controller memanggil ProcessUserPodcast::dispatch($podcast)->onQueue('high');. Laravel mengubah objek Job tersebut menjadi string JSON yang berisi nama kelas, payload data, jumlah percobaan (attempts), dan UUID.
  2. In-Memory Storage: Redis menerima payload tersebut melalui struktur data List (LPUSH) atau ZSet jika menggunakan delayed queue.
  3. Worker Daemon: Supervisor di tingkat sistem operasi Linux memastikan sejumlah proses php artisan queue:work berjalan secara terus-menerus di latar belakang (daemonized).
  4. Execution: Worker mengambil data dari Redis (BRPOP), melakukan deserialisasi objek PHP, dan mengeksekusi metode handle() di dalam Job.

3. Perbandingan Komparatif / Analisis Pendekatan

Memilih driver queue yang tepat sangat menentukan stabilitas infrastruktur jangka panjang. Berikut adalah perbandingan mendalam antara driver Queue populer di ekosistem Laravel:

Fitur / Parameter Redis Driver Database Driver (database) Beanstalkd Amazon SQS
Kecepatan / Latency Sangat Tinggi (In-Memory) Rendah (Disk I/O Bottleneck) Tinggi (C++ daemon) Sedang (Cloud Latency)
Konsumsi RAM Tinggi (Menyimpan di RAM) Sangat Rendah Sedang Sangat Rendah
Skalabilitas Horizontal Sangat Mudah (Redis Cluster) Terbatas oleh beban DB Mudah Sangat Mudah (Cloud Native)
Fitur Lanjutan Delay, Priority, Rate Limiting Terbatas Baik Baik (FIFO/Standard)
Biaya Infrastruktur Membutuhkan RAM server Memanfaatkan DB utama Membutuhkan daemon terpisah Biaya per request AWS

[!TIP]
Untuk aplikasi enterprise skala menengah hingga besar, Redis adalah standar industri mutlak karena kecepatan operasi in-memory yang menghilangkan beban I/O pada database relasional utama (MySQL/PostgreSQL).

4. Prasyarat Sistem & Persiapan Lingkungan

Sebelum melangkah ke implementasi kode, pastikan infrastruktur server (biasanya Ubuntu 22.04 LTS / 24.04 LTS) memiliki komponen berikut:

  • PHP 8.2+ dengan ekstensi redis, pcntl, dan posix.
  • Redis Server terpasang dan berjalan di port standar 6379.
  • Supervisor untuk manajemen proses.

Verifikasi ekstensi PHP yang dibutuhkan dengan perintah terminal:

php -m | grep -E 'redis|pcntl|posix'

Jika ekstensi belum lengkap, instal melalui manajer paket:

sudo apt update
sudo apt install php8.2-redis php8.2-pcntl php8.2-posix redis-server supervisor -y

Pastikan layanan Redis aktif dan berjalan:

sudo systemctl enable --now redis-server
sudo systemctl status redis-server

5. Panduan Implementasi Langkah demi Langkah

Langkah 1: Konfigurasi Environment Laravel (.env)

Buka file .env pada root direktori proyek Laravel Anda dan sesuaikan konfigurasi koneksi Queue:

QUEUE_CONNECTION=redis

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
REDIS_QUEUE=default

Langkah 2: Konfigurasi Driver Redis di config/queue.php

Pastikan koneksi redis pada file konfigurasi menggunakan queue yang sesuai:

// config/queue.php

'connections' => [
    'redis' => [
        'driver' => 'redis',
        'connection' => 'default',
        'queue' => env('REDIS_QUEUE', 'default'),
        'retry_after' => 90,
        'block_for' => null,
        'after_commit' => false,
    ],
],

Langkah 3: Membuat Job Kelas Baru

Buat file job baru menggunakan Artisan CLI:

php artisan make:job ProcessHeavyReport

Isi file app/Jobs/ProcessHeavyReport.php dengan logika bisnis yang siap produksi:

<?php

namespace AppJobs;

use IlluminateBusQueueable;
use IlluminateContractsQueueShouldQueue;
use IlluminateFoundationBusDispatchable;
use IlluminateQueueInteractsWithQueue;
use IlluminateQueueSerializesModels;
use IlluminateSupportFacadesLog;

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

    public int $tries = 3;
    public int $backoff = 60;
    protected array $reportData;

    public function __construct(array $reportData)
    {
        $this->reportData = $reportData;
        $this->onQueue('reports');
    }

    public function handle(): void
    {
        Log::info('Memulai pemrosesan laporan berat ID: ' . $this->reportData['id']);
        
        // Simulasi proses berat (misal: generate PDF & upload ke S3)
        sleep(5);
        
        Log::info('Laporan berhasil diselesaikan.');
    }

    public function failed(Throwable $exception): void
    {
        Log::error('Gagal memproses laporan ID ' . $this->reportData['id'] . ': ' . $exception->getMessage());
    }
}

Langkah 4: Memicu Job dari Controller

<?php

namespace AppHttpControllers;

use AppJobsProcessHeavyReport;
use IlluminateHttpRequest;

class ReportController extends Controller
{
    public function generate(Request $request)
    {
        $data = ['id' => 9982, 'user_id' => $request->user()->id];
        
        // Dispatch job ke antrean secara asynchronous
        ProcessHeavyReport::dispatch($data);

        return response()->json([
            'status' => 'success',
            'message' => 'Laporan sedang diproses di latar belakang.'
        ], 202);
    }
}

Langkah 5: Konfigurasi Supervisor

Buat file konfigurasi Supervisor baru untuk mengelola worker Laravel:

sudo nano /etc/supervisor/conf.d/laravel-worker.conf

Masukkan konfigurasi production-ready berikut:

[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan queue:work redis --queue=reports,default --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killsig=QUIT
user=www-data
numprocs=4
redirect_stderr=true
stdout_logfile=/var/www/html/storage/logs/worker.log
stopwaitsecs=3600

Simpan file, lalu update Supervisor untuk membaca konfigurasi baru:

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

6. Bedah Kode & Penjelasan Detail Baris Kunci

  • public int $tries = 3;: Menentukan batas maksimum percobaan ulang job jika terjadi Exception atau kegagalan koneksi. Jika gagal 3 kali, job akan otomatis dipindahkan ke tabel failed_jobs.
  • public int $backoff = 60;: Jeda waktu (dalam detik) sebelum worker mencoba kembali mengeksekusi job yang gagal. Sangat krusial untuk menghindari lonjakan beban pada layanan eksternal yang sedang down.
  • --queue=reports,default: Pada konfigurasi Supervisor, prioritas antrean ditentukan dari urutan nama queue. Worker akan memprioritaskan antrean reports terlebih dahulu hingga kosong, baru kemudian memproses antrean default.
  • numprocs=4: Memerintahkan Supervisor untuk menjalankan 4 instance worker secara paralel. Ini memaksimalkan utilisasi core CPU server (misalnya server dengan 4 core atau lebih).
  • stopasgroup=true: Memastikan bahwa ketika Supervisor menghentikan proses worker, seluruh sub-proses anak yang mungkin tercipta juga ikut dihentikan secara bersih, mencegah terjadinya orphan process.

7. Skenario Produksi & Studi Kasus Dunia Nyata

[!IMPORTANT] Pada lingkungan high-concurrency dengan ribuan job per detik, penggunaan memori Redis dapat meningkat pesat. Pastikan kebijakan maxmemory dan eviction policy pada Redis dikonfigurasi dengan benar di file /etc/redis/redis.conf:

maxmemory 2gb
maxmemory-policy noeviction

Jangan pernah menggunakan kebijakan volatile-lru atau allkeys-lru untuk queue data, karena penghapusan data queue secara sepihak oleh Redis akan mengakibatkan hilangnya transaksi penting.

8. Common Pitfalls, Anti-Patterns & Solusi

  1. Anti-Pattern: Mengirim Objek Eloquent Bermodel Besar ke dalam Job

    • Masalah: Menyebarkan seluruh instance Model Eloquent ke konstruktor job akan menduplikasi data payload JSON yang sangat besar di Redis.
    • Solusi: Gunakan trait SerializesModels. Cukup teruskan primary key ID model tersebut, lalu ambil kembali model segar di dalam metode handle() menggunakan Model::find($id).
  2. Pitfall: Lupa Menjalankan php artisan config:cache setelah Deploy

    • Masalah: Worker yang sedang berjalan di background tetap memuat konfigurasi lama di memori RAM meskipun kode aplikasi sudah diperbarui.
    • Solusi: Masukkan perintah php artisan queue:restart di dalam script CI/CD deployment Anda setiap kali rilis baru dilakukan.

9. Benchmark, Metrik Kinerja & Tuning Performa

Untuk mengukur keandalan sistem antrean, lakukan pengujian beban menggunakan tool seperti k6 atau Apache Benchmark (ab) pada endpoint yang melakukan dispatch job.

# Contoh pengujian beban menggunakan ab
ab -n 1000 -c 50 https://api.domain.com/api/v1/reports

Parameter Tuning Lanjutan:

  • Atur --memory=512 pada perintah worker untuk memaksa worker melakukan restart mandiri jika konsumsi memori PHP melewati 512MB, mencegah potensi memory leak dari library pihak ketiga.
  • Gunakan Redis Cluster atau Redis Sentinel untuk ketersediaan tinggi (High Availability) pada infrastruktur multi-server.

10. Checklist Penerapan Produksi & Kesimpulan

Sebelum meluncurkan sistem ke lingkungan production, pastikan seluruh poin dalam checklist berikut terpenuhi:

  • Ekstensi PHP pcntl dan posix terinstal dengan benar.
  • Redis dilindungi dengan password authentication dan akses jaringan internal yang ketat.
  • Supervisor dikonfigurasi dengan autostart=true dan autorestart=true.
  • Tabel failed_jobs sudah dibuat melalui migrasi database Laravel (php artisan queue:failed-table).
  • Sistem monitoring log worker aktif (misalnya menggunakan Sentry, Datadog, atau rotasi log bawaan Logrotate).

Dengan menerapkan arsitektur Event-Driven berbasis Redis Queue dan Supervisor ini, aplikasi Laravel Anda tidak hanya akan memiliki performa respons HTTP yang luar biasa cepat, tetapi juga ketahanan infrastruktur yang kokoh dalam menghadapi lonjakan beban kerja enterprise.

🏷️ Tags: #Nginx #High Concurrency #Performance #Sysadmin #Web Server