Cara Menggunakan Horizon

Memproses tugas-tugas berat di aplikasi web, seperti mengirim ribuan email, mengelola notifikasi real-time, atau melakukan komputasi kompleks, seringkali menjadi bottleneck. Jika tugas-tugas ini dieksekusi secara langsung, pengguna akan merasakan respons aplikasi yang lambat, bahkan timeout. Di sinilah antrean (queue) berperan penting, dan Laravel Horizon adalah solusi elegan untuk mengelola antrean di ekosistem Laravel.

Sebagai seorang developer yang sering berurusan dengan aplikasi skala produksi, saya paham betul betapa krusialnya memiliki sistem antrean yang robust dan mudah dimonitor. Tanpa Horizon, mengelola queue worker bisa jadi mimpi buruk, apalagi saat menghadapi lonjakan traffic atau kegagalan tak terduga. Artikel ini akan memandu Anda secara mendalam tentang cara menggunakan Horizon, mulai dari instalasi hingga optimasi, lengkap dengan insight praktis dan solusi untuk masalah yang sering terjadi.

Apa itu Laravel Horizon dan Kenapa Anda Membutuhkannya?

Laravel Horizon adalah dashboard dan sistem konfigurasi canggih untuk antrean Redis yang ada di Laravel. Secara sederhana, Horizon memberikan Anda visibilitas penuh dan kontrol granular terhadap semua proses antrean di aplikasi Laravel Anda. Bayangkan Anda memiliki puluhan, bahkan ratusan, background jobs yang berjalan simultan. Tanpa Horizon, melacak status, kinerja, atau kegagalan job-job tersebut akan sangat sulit.

Horizon dibangun di atas Redis, sebuah key-value store in-memory yang sangat cepat, menjadikannya pilihan ideal untuk backend antrean. Dengan Horizon, Anda tidak hanya dapat menjalankan dan memonitor worker, tetapi juga mengelola retry, failed jobs, metrik kinerja, dan bahkan mendapatkan notifikasi jika ada masalah.

Kenapa Anda membutuhkannya? Karena ini bukan hanya tentang memindahkan tugas ke latar belakang. Ini tentang:

  • Skalabilitas: Mudah menambah atau mengurangi jumlah worker untuk menangani beban kerja yang bervariasi.
  • Reliabilitas: Fitur retry otomatis untuk failed jobs dan visibilitas ke dalam kegagalan.
  • Observability: Dashboard real-time yang menunjukkan throughput, waktu eksekusi, dan status worker.
  • Kemudahan Manajemen: Konfigurasi worker melalui file PHP, bukan lagi mengandalkan banyak perintah php artisan queue:work atau konfigurasi Supervisor yang rumit secara manual.

Jika aplikasi Anda mulai melibatkan tugas-tugas non-real-time yang bisa dieksekusi di latar belakang—seperti integrasi API pihak ketiga, pemrosesan data, atau pengiriman email massal—maka Horizon adalah investasi waktu yang sangat berharga.

Prasyarat Sebelum Menginstal Laravel Horizon

Sebelum kita mulai menginstal dan mengkonfigurasi Laravel Horizon, ada beberapa prasyarat yang perlu Anda siapkan:

  1. Proyek Laravel: Tentu saja, Anda memerlukan instalasi proyek Laravel yang sudah berjalan.
  2. PHP 8.0+ : Pastikan versi PHP Anda kompatibel dengan Laravel Horizon.
  3. Composer: Untuk mengelola dependensi PHP.
  4. Redis Server: Horizon menggunakan Redis sebagai driver antrean utamanya. Anda harus menginstal dan menjalankan Redis server di mesin Anda (lokal atau di server produksi).
  5. Konfigurasi Redis di Laravel: Pastikan Anda telah mengkonfigurasi koneksi Redis di file .env dan config/database.php Laravel Anda. Contoh konfigurasi di .env:

    REDIS_HOST=127.0.0.1
    REDIS_PASSWORD=null
    REDIS_PORT=6379

  6. Konfigurasi Queue Driver: Pastikan QUEUE_CONNECTION di file .env Anda diatur ke redis:

    QUEUE_CONNECTION=redis

Langkah Demi Langkah Instalasi Laravel Horizon

Mari kita mulai dengan proses instalasi dan konfigurasi Horizon.

1. Instalasi Redis Server

Jika Anda belum memiliki Redis, Anda bisa menginstalnya. Di Ubuntu, perintahnya adalah:

sudo apt update
sudo apt install redis-server

Setelah instalasi, pastikan Redis berjalan:

sudo systemctl status redis-server

2. Instalasi dan Konfigurasi Laravel Horizon

Pertama, instal paket Horizon melalui Composer:

composer require laravel/horizon

Setelah itu, publish aset Horizon:

php artisan horizon:install

Perintah ini akan membuat file konfigurasi config/horizon.php dan aset lainnya yang diperlukan.

Di file .env Anda, pastikan Anda telah mengatur lingkungan untuk Horizon. Secara default, Horizon hanya aktif di lingkungan local. Untuk produksi, Anda mungkin perlu mengubahnya:

HORIZON_ENV=production (atau biarkan kosong jika Anda ingin Horizon aktif di semua lingkungan)

3. Menulis Job Pertama Anda

Mari kita buat job sederhana untuk menguji Horizon. Gunakan Artisan:

php artisan make:job SendWelcomeEmail

Buka file app/Jobs/SendWelcomeEmail.php dan tambahkan logika sederhana:

<?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;
use Illuminate\Support\Facades\Log;

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

    protected $userEmail;

    /
     * Create a new job instance.
     */
    public function __construct($userEmail)
    {
        $this->userEmail = $userEmail;
    }

    /
     * Execute the job.
     */
    public function handle(): void
    {
        // Simulasi pengiriman email
        sleep(5); // Anggap ini proses yang butuh 5 detik
        Log::info("Sending welcome email to: " . $this->userEmail);
        // Di sini Anda bisa memanggil Mail::to($this->userEmail)->send(new WelcomeEmail());
    }
}

Untuk men-dispatch job ini, Anda bisa memanggilnya dari controller atau bagian lain di aplikasi Anda:

<?php

namespace App\Http\Controllers;

use App\Jobs\SendWelcomeEmail;
use Illuminate\Http\Request;

class UserController extends Controller
{
    public function register(Request $request)
    {
        // Logika registrasi user...

        // Dispatch job setelah user terdaftar
        SendWelcomeEmail::dispatch($request->email);

        return response()->json(['message' => 'User registered and welcome email queued!']);
    }
}

4. Menjalankan Worker Horizon

Untuk menjalankan Horizon, Anda bisa menggunakan perintah Artisan:

php artisan horizon

Perintah ini akan memulai Horizon dan worker-worker Anda akan mulai memproses jobs dari antrean Redis. Namun, untuk lingkungan produksi, Anda tidak boleh menjalankan perintah ini secara langsung. Anda harus menggunakan proses manajer seperti Supervisor untuk memastikan Horizon terus berjalan dan me-restart otomatis jika terjadi kegagalan.

Konfigurasi Supervisor untuk Horizon:

Instal Supervisor jika belum ada:

sudo apt install supervisor

Buat file konfigurasi Supervisor untuk Horizon, misalnya /etc/supervisor/conf.d/horizon.conf:

[program:horizon]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/your-project/artisan horizon
autostart=true
autorestart=true
user=www-data ; Ganti dengan user web server Anda
numprocs=1
redirect_stderr=true
stdout_logfile=/var/www/html/your-project/storage/logs/horizon.log
stopwaitsecs=3600

Pastikan untuk mengganti /var/www/html/your-project dengan path root proyek Laravel Anda dan www-data dengan user yang benar (biasanya user web server seperti nginx atau apache).

Setelah membuat file konfigurasi, muat ulang Supervisor:

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start horizon:*

5. Mengakses Dashboard Horizon

Setelah Horizon berjalan, Anda bisa mengakses dashboard-nya melalui URL:

http://your-app-domain.com/horizon

Secara default, Horizon hanya bisa diakses di lingkungan local atau jika Anda sedang login sebagai user yang diperbolehkan di konfigurasi config/horizon.php. Untuk produksi, Anda perlu melindungi akses ke dashboard Horizon, misalnya dengan otentikasi. Anda bisa mengkonfigurasi gate otentikasi di app/Providers/HorizonServiceProvider.php:

/
 * Register the Horizon gate.
 *
 * This gate determines who can access Horizon in non-local environments.
 */
protected function gate(): void
{
    Gate::define('viewHorizon', function ($user) {
        return in_array($user->email, [
            'admin@example.com',
        ]);
    });
}

Ganti 'admin@example.com' dengan email user admin Anda.

Fitur Unggulan Laravel Horizon untuk Monitoring Queue

Dashboard Horizon bukan sekadar tampilan statis; ini adalah pusat komando real-time untuk antrean Anda.

  • Real-time Monitoring: Lihat job yang sedang berjalan, job yang menunggu, job yang gagal, dan throughput secara instan.
  • Metrik dan Throughput: Horizon menampilkan metrik penting seperti rata-rata waktu eksekusi job, jumlah job per menit, dan penggunaan memori worker. Ini sangat berguna untuk mengidentifikasi bottleneck.
  • Retry dan Failed Jobs: Mudah melihat detail failed jobs, termasuk exception stack trace, dan me-retry job tersebut secara manual.
  • Batches: Jika Anda menggunakan job batching di Laravel (memproses sekelompok job secara bersamaan dan mendapatkan notifikasi saat semua job selesai), Horizon menyediakan tampilan khusus untuk memonitor status batch.
  • Notifikasi: Konfigurasi Horizon untuk mengirim notifikasi ke Slack atau email saat queue dalam kondisi kritis (misalnya, terlalu banyak failed jobs).

Fitur-fitur ini sangat membantu dalam menjaga kesehatan aplikasi, terutama saat aplikasi tumbuh dan beban kerja antrean meningkat.

Konfigurasi Lanjut dan Optimasi Laravel Horizon

File config/horizon.php adalah tempat Anda mengkonfigurasi semua aspek Horizon. Beberapa pengaturan penting yang sering dioptimasi:

1. Strategi Balance Worker

Horizon memiliki tiga strategi balancing:

  • simple: Mendistribusikan job secara merata ke semua worker.
  • auto: Horizon akan mencoba menyeimbangkan jumlah worker berdasarkan beban antrean. Ini adalah opsi yang paling umum dan direkomendasikan.
  • false: Menonaktifkan fitur balancing, Anda harus mengelola jumlah worker secara manual.

Anda bisa mengatur ini di config/horizon.php:

'defaults' => [
'supervisor-name' => [
'connection' => 'redis',
'queue' => ['default'],
'balance' => 'auto', // Pilihan: auto, simple, false
'min_processes' => 1,
'max_processes' => 10,
'tries' => 3,
],
],

2. Membuat Supervisor Kustom

Anda bisa mendefinisikan beberapa “supervisor” di Horizon, masing-masing dengan konfigurasi worker yang berbeda. Misalnya, Anda ingin worker untuk antrean emails memiliki prioritas lebih tinggi atau resource lebih besar daripada antrean default.

'supervisors' => [
    'default' => [
        'connection' => 'redis',
        'queue' => ['default', 'reports'], // Antrean untuk supervisor ini
        'balance' => 'auto',
        'min_processes' => 1,
        'max_processes' => 5,
        'tries' => 3,
        'timeout' => 120, // Timeout per job dalam detik
    ],
    'email_processor' => [
        'connection' => 'redis',
        'queue' => ['emails'], // Hanya memproses antrean 'emails'
        'balance' => 'auto',
        'min_processes' => 2,
        'max_processes' => 10,
        'tries' => 5,
        'timeout' => 300,
        'memory' => 512, // Batas memori per worker dalam MB
    ],
],

Dengan konfigurasi ini, Anda bisa memiliki worker yang didedikasikan untuk tugas-tugas tertentu, memberikan fleksibilitas dan kontrol yang lebih baik atas prioritas dan resource.

3. Menggunakan Multiple Queue Connections

Meskipun Horizon utamanya menggunakan Redis, Anda masih bisa memiliki koneksi antrean lain yang didefinisikan di config/queue.php. Horizon akan fokus pada koneksi yang Anda tetapkan di konfigurasinya.

4. Limitasi Resource Worker

Setiap worker Horizon adalah proses PHP terpisah. Penting untuk membatasi resource yang bisa mereka gunakan untuk mencegah satu worker memonopoli semua resource server. Pengaturan memory di konfigurasi supervisor sangat membantu. Horizon juga memiliki fitur max_time dan max_jobs untuk me-restart worker setelah periode waktu atau jumlah job tertentu, mencegah kebocoran memori.

Pengalaman dan Pertimbangan Praktis Saat Menggunakan Horizon

Sebagai praktisi yang sering mengimplementasikan Horizon di berbagai proyek, ada beberapa pengalaman dan pertimbangan yang ingin saya bagikan:

  • Kapan Horizon Menjadi Sangat Berharga?

    Di project skala kecil dengan hanya beberapa job per hari, Horizon mungkin terasa overkill. Anda bisa bertahan dengan php artisan queue:work dan Supervisor manual. Namun, begitu Anda mulai melihat puluhan atau ratusan job per jam, atau Anda memiliki kebutuhan untuk melacak metrik kinerja antrean, itulah saat Horizon benar-benar bersinar. Dashboard-nya sangat membantu saat debugging masalah antrean atau memonitor kinerja di produksi.

  • Tantangan Implementasi di Produksi

    Salah satu tantangan umum adalah memastikan Supervisor dikonfigurasi dengan benar, terutama terkait user permission dan path proyek. Seringkali, Horizon tidak bisa menulis log atau memulai worker karena masalah izin file. Pastikan user yang menjalankan Supervisor memiliki izin yang cukup untuk mengakses folder proyek Laravel Anda, terutama storage dan bootstrap/cache.

    Selain itu, memonitor penggunaan Redis juga penting. Jika antrean Anda sangat padat, Redis bisa menjadi bottleneck. Pastikan Redis server Anda memiliki cukup RAM dan CPU, atau pertimbangkan untuk meng-cluster Redis jika beban sangat tinggi.

  • Biaya Redis dan Skalabilitas

    Menggunakan Redis sebagai backend antrean memang cepat, tetapi juga berarti Anda perlu mengalokasikan resource untuk Redis. Untuk aplikasi skala besar, Anda mungkin perlu mempertimbangkan managed Redis service seperti Amazon ElastiCache atau Redis Enterprise, yang tentu memiliki biaya tambahan. Horizon sendiri tidak memakan banyak resource, tetapi worker-worker PHP di baliknya yang akan mengkonsumsi memori dan CPU tergantung kompleksitas job Anda.

  • Alternatif Jika Horizon Terlalu Overkill

    Jika kebutuhan antrean Anda sangat sederhana dan Anda ingin menghindari dependensi Redis atau Horizon, Anda bisa menggunakan database queue driver Laravel. Ini lebih lambat dan tidak seefisien Redis, tetapi lebih mudah di-setup untuk kasus penggunaan dasar. Namun, Anda akan kehilangan semua fitur monitoring dan manajemen canggih yang ditawarkan Horizon.

Masalah yang Sering Terjadi Saat Menggunakan Laravel Horizon

Meskipun Horizon sangat membantu, ada beberapa masalah umum yang sering saya temui (dan mungkin Anda juga) saat mengimplementasikannya:

1. Job Tidak Dieksekusi

  • Gejala: Anda men-dispatch job, tetapi tidak muncul di dashboard Horizon atau tidak pernah dieksekusi.
  • Penyebab:
    • Worker Horizon belum berjalan (php artisan horizon atau Supervisor tidak aktif).
    • QUEUE_CONNECTION di .env tidak diatur ke redis.
    • Redis server tidak berjalan atau tidak dapat diakses dari aplikasi Laravel.
    • Antrean (queue) yang Anda dispatch tidak diproses oleh supervisor Horizon. (e.g., job MyJob::dispatch()->onQueue('high_priority'); tapi supervisor Horizon tidak mengawasi antrean high_priority).
  • Solusi:
    • Pastikan Horizon berjalan dengan php artisan horizon atau cek status Supervisor (sudo supervisorctl status).
    • Periksa file .env dan config/queue.php.
    • Cek koneksi ke Redis menggunakan redis-cli ping atau coba flush Redis cache jika ada masalah.
    • Pastikan konfigurasi supervisors di config/horizon.php mencakup semua nama antrean (queue) yang Anda gunakan.

2. Dashboard Horizon Tidak Muncul atau Error 403

  • Gejala: Saat mengakses /horizon, Anda mendapatkan 404 (Not Found) atau 403 (Forbidden).
  • Penyebab:
    • Aset Horizon belum di-publish atau ada masalah routing.
    • Anda tidak berada di lingkungan local, dan Anda belum mengkonfigurasi gate otentikasi di HorizonServiceProvider.
  • Solusi:
    • Jalankan ulang php artisan horizon:install dan php artisan config:clear, lalu pastikan web server Anda (Nginx/Apache) dikonfigurasi dengan benar untuk Laravel (misalnya, semua permintaan diarahkan ke public/index.php).
    • Konfigurasi gate otentikasi di app/Providers/HorizonServiceProvider.php seperti yang dijelaskan di atas.

3. Out of Memory atau Resource Terbatas

  • Gejala: Job gagal dengan pesan “Allowed memory size of X bytes exhausted” atau server menjadi sangat lambat.
  • Penyebab:
    • Job Anda mengkonsumsi terlalu banyak memori (misalnya, memproses file besar atau mengambil data dalam jumlah masif).
    • Jumlah worker terlalu banyak untuk resource server yang tersedia.
    • Memory leak di salah satu job atau dependensinya.
  • Solusi:
    • Optimasi job Anda agar lebih efisien dalam penggunaan memori. Pecah job besar menjadi job-job yang lebih kecil jika memungkinkan.
    • Kurangi jumlah max_processes atau tingkatkan nilai memory di konfigurasi supervisor Horizon (config/horizon.php).
    • Aktifkan max_jobs atau max_time di konfigurasi Horizon untuk me-restart worker secara berkala, membantu membersihkan memori yang mungkin bocor.
    • Upgrade resource server (RAM, CPU).

4. Horizon Terhenti Mendadak

  • Gejala: Horizon worker berhenti memproses job, dan dashboard menunjukkan worker tidak aktif.
  • Penyebab:
    • Tidak menggunakan Supervisor di produksi, sehingga proses php artisan horizon terhenti (misalnya, karena sesi SSH putus).
    • Ada exception yang tidak tertangani di salah satu job, menyebabkan worker mati.
    • Server kehabisan resource (RAM/CPU) dan sistem membunuh proses Horizon.
  • Solusi:
    • Selalu gunakan Supervisor di lingkungan produksi. Ini adalah solusi paling penting untuk masalah ini.
    • Pastikan semua job Anda memiliki penanganan exception yang tepat. Gunakan try-catch di dalam metode handle() job.
    • Periksa log Horizon (storage/logs/horizon.log) dan log aplikasi Laravel Anda (storage/logs/laravel.log) untuk melihat error yang mungkin terjadi.
    • Memonitor resource server secara berkala.

FAQ

Apa perbedaan Horizon dengan php artisan queue:work biasa?

php artisan queue:work adalah perintah dasar untuk menjalankan satu proses worker. Horizon adalah lapisan di atasnya yang menyediakan dashboard monitoring real-time, manajemen worker yang canggih (balancing, scaling), fitur retry/fail otomatis, dan konfigurasi yang lebih mudah melalui file PHP daripada pengaturan Supervisor manual.

Apakah Horizon memerlukan Redis?

Ya, secara fundamental Laravel Horizon dirancang untuk bekerja dengan Redis sebagai driver antrean. Anda harus menginstal dan menjalankan Redis server untuk menggunakan Horizon.

Bisakah saya menggunakan Horizon tanpa Supervisor?

Secara teknis bisa untuk development (dengan menjalankan php artisan horizon), tetapi sangat tidak disarankan untuk lingkungan produksi. Supervisor memastikan proses Horizon tetap berjalan di latar belakang, me-restart otomatis jika terjadi kegagalan, dan mengelola worker dengan andal, yang krusial untuk aplikasi produksi.

Bagaimana cara menghentikan Horizon?

Jika Anda menjalankan Horizon secara manual, tekan Ctrl+C. Jika menggunakan Supervisor, gunakan perintah sudo supervisorctl stop horizon:*.

Kesimpulan

Mengelola background jobs adalah aspek penting dalam pengembangan aplikasi modern, terutama saat aplikasi tumbuh dan memerlukan skalabilitas serta efisiensi. Laravel Horizon menawarkan solusi yang powerful dan elegan untuk tantangan ini, mengubah manajemen antrean dari tugas yang membosankan menjadi proses yang transparan dan terkontrol. Dengan Horizon, Anda tidak hanya dapat memproses job di latar belakang, tetapi juga memiliki pandangan mata burung (bird’s eye view) ke seluruh sistem antrean Anda, memastikan aplikasi tetap responsif dan andal.

Dari instalasi dasar hingga optimasi lanjutan dan penanganan masalah umum, semoga panduan ini memberikan Anda kepercayaan diri untuk mengimplementasikan Laravel Horizon di proyek-proyek Anda. Mulailah memanfaatkan kekuatan queueing dengan Horizon dan rasakan perbedaannya dalam performa dan manajemen aplikasi Anda!

TAGS: Laravel Horizon, Queue, Redis, Background Jobs, PHP, Developer Tools, Laravel, Worker, Supervisor, Monitoring


Baca Juga

You May Also Like

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *