Cara menjeda dan mengontrol antrian di Laravel langkah demi langkah

Pembaharuan Terakhir: Desember 5 2025
  • Laravel menawarkan API antrean terpadu dengan beberapa driver (database, Redis, SQS…) dan pemisahan antara koneksi dan antrean logis.
  • Pekerjaan memungkinkan tugas berat dipindahkan ke latar belakang, dengan dukungan untuk serialisasi model, middleware, pekerjaan satu kali, enkripsi, batch, dan string.
  • Pekerja dikelola dengan queue:work, Supervisor dan perintah seperti queue:pause/queue:continue, yang mengendalikan percobaan ulang, batas waktu dan prioritas.
  • Terdapat ekosistem lengkap untuk kegagalan, pemantauan, dan pengujian (failed_jobs, queue:retry, queue:monitor, Queue::fake) yang membuat antrean andal dalam produksi.

Manajemen antrian di Laravel

Bekerja dengan antrean (queue) di Laravel hampir wajib dalam proyek yang cukup serius: mengirim email, memproses file CSV, membuat PDF, mengubah ukuran gambar, memanggil API eksternal… Jika semua itu dilakukan dalam permintaan HTTP utama, situs web akan menjadi lambat, muncul kesalahan 500, dan pengguna akhirnya hanya bisa menatap layar kosong dengan putus asa.

Kabar baiknya adalah Laravel menawarkan infrastruktur antrian yang kuat dan fleksibel yang memungkinkan Anda mendelegasikan tugas berat ke proses latar belakang, mengelolanya berdasarkan prioritas, mengelompokkannya ke dalam batch, memantaunya, mencoba lagi jika gagal, dan bahkan menghentikan sementara worker untuk pemeliharaan. Mari kita lihat lebih dekat (dan jangan sampai ada yang terlewat) bagaimana cara memaksimalkannya, termasuk cara menghentikan sementara, melanjutkan, dan mengontrol perilakunya di lingkungan produksi.

Konsep dasar: koneksi, antrian, dan driver

Di Laravel, sebelum menjeda apa pun, Anda perlu memahami perbedaan antara koneksi antrian dan antrian itu sendiri. Di config/queue.php Anda memiliki sebuah array connections di mana Anda mendefinisikan setiap backend: basis data, redis, beanstalkd, sqs, sinkronisasi, null, failover, rabbitmq (jika Anda menambahkannya), dll.

Setiap koneksi dapat memiliki beberapa antrian logis (nama seperti default, emails, high, low, importsAtribut queue Setiap koneksi mengindikasikan antrian default tempat pekerjaan akan pergi jika tidak ada yang lain yang ditentukan. onQueue()Dengan cara ini Anda dapat melakukan hal-hal seperti:

  • Antrian cepat untuk email atau transaksi singkat.
  • Prioritas rendah lainnya untuk tugas yang panjang seperti memproses video atau laporan besar.
  • Antrean dibagi berdasarkan jenis tugas: imports, notificaciones, reportes, Dll

Saat Anda meluncurkan pekerja dengan php artisan queue:workSecara default, ia mendengarkan antrian yang ditentukan sebagai default pada koneksi yang dipilih. Jika Anda ingin memprioritaskan, Anda dapat meneruskan beberapa antrean yang dipisahkan koma:

php artisan queue:work redis --queue=high,default,low

Dengan cara ini, pekerja memproses prioritas tinggi terlebih dahulu , kemudian prioritas standar , dan baru kemudian prioritas rendah , yang sangat penting ketika sistem sedang sibuk dan Anda tidak ingin laporan selama 30 menit menghalangi email prioritas tinggi.

Pengemudi antrian dan prasyaratnya

Laravel menawarkan API terpadu untuk beberapa driver antrian , tetapi masing-masing memiliki fitur dan dependensi spesifiknya sendiri. Memilih driver yang tepat sangat penting sebelum membahas tentang menghentikan sementara worker.

Basis data pengemudi

Supir Database Ini menyimpan pekerjaan dalam tabel SQL (biasanya jobsMudah diatur dan cocok untuk proyek kecil atau lingkungan pengembangan di mana Anda tidak ingin repot dengan Redis atau SQS.

Langkah-langkah dasar:

  • Hasilkan migrasi: php artisan queue:table (atau dalam versi yang lebih baru, hadir sebagai create_jobs_table bawaan).
  • Jalankan migrasi: php artisan migrate.
  • Konfigurasikan QUEUE_CONNECTION=basis data di .env dan konfirmasi config/queue.php bahwa 'default' => env('QUEUE_CONNECTION','database').

Sistem ini praktis dan cukup andal, tetapi dengan banyak antrian dan lalu lintas yang padat, sistem ini dapat menjadi hambatan , karena semuanya melewati basis data relasional yang sama.

Pengemudi Redis

Driver Redis adalah andalan standar dalam lingkungan produksi. Ia cepat, mendukung fitur-fitur canggih (penguncian, pembatasan laju, penguncian atomik, Horizon, dll.), dan memiliki skalabilitas yang sangat baik.

Poin penting:

  • Anda perlu mengonfigurasi koneksi Redis di config/database.php.
  • Pilihannya serializer y compression dari Redis Mereka tidak kompatibel dengan pengemudi antrean.
  • Jika Anda menggunakan Gugus RedisNama antrian harus memiliki tagar, misalnya {default}sehingga semua kunci dalam antrian itu jatuh ke slot yang sama.
  • pilihan block_for Hal ini memungkinkan pekerja untuk memblokir sambil menunggu pekerjaan selama beberapa detik, alih-alih melakukan polling terus-menerus: menghemat CPU dan mengurangi kueri ke server Redis.

Sebagai contoh:

'redis' => ,

Jika Anda menaruh blok_untuk = 0Pekerja tetap diblokir tanpa batas waktu hingga pekerjaan tersedia, sesuatu yang perlu diingat jika Anda ingin merespons dengan cepat sinyal seperti SIGTERM atau perintah jeda.

Driver lainnya: SQS, Beanstalkd, null, failover…

Selain basis data dan Redis, Laravel mendukung sistem lain :

  • Amazon SQSAntrean terkelola di AWS, dengan dukungan untuk FIFOGrup pesan, deduplikasi, dan pengaturan visibilitas lanjutan. Memerlukan SDK. aws/aws-sdk-php.
  • Pohon kacangSangat cepat dan mudah, menggunakan paket pda/pheanstalk.
  • sinkronisasi: melakukan tugas-tugas segera dalam proses yang sama. Berguna dalam pengembangan atau pengujian, tetapi dalam produksi, praktis seperti tidak menggunakan antrean sama sekali.
  • nol: Membuang pekerjaan segera setelah "dikirim". Digunakan untuk menonaktifkan sistem antrean sepenuhnya.
  • kegagalanIni memungkinkan Anda mengonfigurasi beberapa koneksi, dan jika koneksi utama gagal, Laravel akan mencoba memindahkan pekerjaan ke koneksi berikutnya dalam daftar. Sempurna untuk lingkungan di mana ketersediaan tinggi sangat penting.
  Desain web profesional: panduan lengkap untuk situs web yang menghasilkan konversi.

Pada level menghentikan sementara dan melanjutkan pekerja, logikanya praktis sama terlepas dari driver yang digunakan, karena dikelola dari perintah Artisan dan kelas Worker , bukan dari backend antrian.

Pembuatan pekerjaan dan serialisasi model

Un Pekerjaan Di Laravel, ini hanyalah kelas yang merangkum tugas yang akan dieksekusi dalam antrean. Biasanya dibuat dengan Artisan dan disimpan di app/Jobs.

Untuk membuat satu:

php artisan make:job ProcessPodcast

Kelas yang dihasilkan mengimplementasikan ShouldQueue dan biasanya menggunakan sifat-sifat Dispatchable, InteractsWithQueue, Queueable y SerializesModelsHati ada dalam metode handle()yang dilakukan pekerja saat pekerjaan tiba.

Salah satu fitur yang sangat ampuh adalah serialisasi otomatis model Eloquent . Jika Anda menerima model di konstruktor Job, Laravel tidak menambahkan seluruh objek ke antrian, hanya pengidentifikasinya saja. Saat job diproses, ia akan merekonstruksi model dari database dengan relasi yang sudah dimuat.

Contoh umum (dalam pseudocode, untuk menghindari pengulangan kata demi kata):

  • Pembangun menerima Podcast $podcast.
  • Sifat SerializesModels Bertanggung jawab untuk menyimpan ID.
  • En handle(AudioProcessor $processor) Anda melakukan kerja keras (memproses audio, misalnya).

Jika Anda tidak ingin hubungan dalam model diserialkan (jadi muatannya tidak besar), Anda dapat menggunakan $model->withoutRelations() atau di PHP 8 atributnya # pada properti yang dipromosikan oleh pembangun.

Injeksi ketergantungan dalam metode pegangan

Keuntungan lainnya adalah Anda bisa menyuntikkan layanan langsung ke metode pegangan (seolah-olah itu adalah pengontrol), karena Laravel juga menggunakan kontainer layanan di Jobs. Misalnya, Anda dapat meminta AudioProcessorKlien HTTP, repositori, dsb., dan kerangka kerja menangani penyelesaiannya.

Jika Anda membutuhkan kontrol ultra-halus dari apa yang disebut handlekamu bisa menggunakan Container::bindMethod() pada penyedia layanan dan tentukan sendiri logika injeksinya, tetapi dalam sebagian besar kasus tidak perlu terlalu memperumit masalah.

Middleware Pekerjaan

Sama seperti rute yang memiliki middleware, Pekerjaan juga dapat memiliki middleware tertentu yang berjalan sebelum dan sesudah pekerjaan. Hal ini sangat mengurangi kode berulang dalam metode handle() dan sangat berguna untuk:

  • Pembatasan tarif dengan Redis.
  • Menghindari tumpang tindih karya yang menyentuh sumber daya yang sama.
  • Pengecualian reguler untuk API yang tidak stabil.
  • Melewati pekerjaan dalam kondisi tertentu (Skip middleware).

Middleware biasanya ditempatkan di app/Jobs/Middleware dan dikembalikan dari metode middleware() Dari Ayub. Contoh konseptual:

public function middleware(): array { return ;

Jenis pekerjaan khusus: unik, terenkripsi, dan terkunci

Laravel memungkinkan Anda menandai pekerjaan tertentu sebagai unik untuk memastikan tidak ada dua instance identik yang pernah diantrekan pada saat yang bersamaan. Hal ini dicapai dengan mengimplementasikan antarmuka ShouldBeUnique o ShouldBeUniqueUntilProcessingdan mendukung pendefinisian kunci uniqueId() dan suatu waktu uniqueFor.

Ini ideal untuk hal-hal seperti:

  • Hitung ulang indeks pencarian produk: hanya sekali per produk sampai selesai.
  • Sinkronisasi dengan layanan eksternal yang tidak mengizinkan permintaan bersamaan untuk sumber daya yang sama.

Di bawahnya, Laravel menggunakan kunci atom cache (Redis, memcached, database, dll.). Anda juga dapat memilih driver cache untuk kunci tersebut dengan uniqueVia().

Selain itu ada juga interface ShouldBeEncrypted, yang dengannya Anda menunjukkan bahwa Pekerjaan lengkapnya Masukkan kode Anda sebelum memasuki antrianSangat berguna saat mengirimkan data sensitif dan Anda tidak ingin data tersebut dikirimkan dalam bentuk teks biasa melalui Redis, SQS atau basis data.

Mengirim, menunda, dan mengeksekusi pekerjaan dalam berbagai mode

Setelah pekerjaan Anda ditentukan, Anda meluncurkannya dengan Job::dispatch() dari pengontrol, pendengar acara, perintah Artisan, atau bahkan penutupan. Parameter yang Anda berikan ke dispatch Mereka langsung pergi ke pembangun Ayub.

Variasi yang menarik:

  • dispatchIf() y dispatchUnless() untuk mengondisikan pengiriman dalam satu baris.
  • delay() sehingga pekerjaan tidak dapat diproses hingga tanggal/waktu tertentu.
  • dispatchAfterResponse() o afterResponse() en dispatch() Penutupan, yang menunda eksekusi hingga respons HTTP telah dikirim, tetapi dalam proses PHP yang sama.
  • dispatchSync() untuk menjalankan Pekerjaan secara sinkron (tanpa melalui antrian) tetapi menggunakan kembali kelas yang sama.
  • Koneksi khusus seperti deferred o background untuk dieksekusi setelah respons, dalam proses yang sama atau dalam proses PHP baru.

Terakhir, Anda dapat menentukan koneksi dan antrean dengan metode berantai onConnection() y onQueue(), baik saat pengiriman atau dalam pembuat Pekerjaan.

Kontrol halus: percobaan ulang, penundaan, batas waktu, dan penanganan kesalahan

Sebagian besar dari bekerja dengan antrian di Laravel adalah memutuskan berapa kali suatu pekerjaan harus dicoba ulang , berapa lama waktu tunggu antar percobaan, dan kapan pekerjaan tersebut dianggap gagal.

  Panduan Lengkap OpenCode: Cara Memprogram dengan AI menggunakan ChatGPT, Claude, dan Gemini

Pilihan yang tersedia:

  • --tries en queue:work untuk menetapkan jumlah percobaan maksimum untuk semua pekerjaan pekerja tersebut (kecuali Pekerjaan menentukan sendiri) $tries o tries()).
  • $tries atau suatu metode tries() di kelas Pekerjaan untuk kontrol per-Pekerjaan.
  • retryUntil() mengatakan: “coba lagi semampumu sampai saat ini, setelah itu gagal.” Jika bertepatan dengan tries, memerintah retryUntil.
  • $maxExceptions untuk memotong ketika masalah disebabkan oleh pengecualian yang berulang dan tidak tertangani.
  • $timeout o --timeout untuk menunjukkan berapa detik suatu Pekerjaan dapat berjalan sebelum pekerja menghentikan proses anak.
  • $failOnTimeout untuk menandai pekerjaan sebagai gagal jika batas waktu habis.
  • $backoff metode backoff() untuk menentukan berapa lama menunggu antara percobaan ulang, bahkan dengan nilai eksponensial.

Jika suatu pekerjaan memunculkan pengecualian yang tidak tertangkap, Laravel akan... melepaskan lagi ke ekor hingga upaya yang dikonfigurasi habis. Anda dapat mengontrolnya secara manual dengan release($segundos) o fail($exception) ketika Anda ingin sengaja menandai pekerjaan sebagai gagal.

Pekerjaan yang gagal, tabel failed_jobs dan pemangkasan

Ketika seorang Job sudah kehabisan tenaga, dia akan dianggap pekerjaan yang gagal dan Laravel memasukkannya ke dalam tabel failed_jobs (atau di DynamoDB jika Anda mengonfigurasinya seperti itu). Tabel tersebut menyimpan UUID, koneksi, antrean, muatan pekerjaan, dan pengecualian yang dilemparkan.

Perintah yang berguna:

  • php artisan queue:failed untuk mencantumkan yang gagal.
  • php artisan queue:retry <id|all> untuk mencobanya lagi.
  • php artisan queue:forget <id> untuk menghapus satu.
  • php artisan queue:flush untuk menghapus semua (dengan opsi jam pada versi yang lebih baru).
  • php artisan queue:prune-failed --hours=48 untuk memangkas rekaman lama secara otomatis.

Di Jobs Anda dapat menentukan metode failed(Throwable $exception) Untuk pembersihan ekstra: beri tahu pengguna, kembalikan tindakan parsial, tulis log khusus, dll. Perhatikan bahwa instance baru dari Job dibuat untuk memanggil failed()Oleh karena itu, jangan bergantung pada perubahan properti yang dilakukan di handle().

Pengelompokan pekerjaan: pengelompokan pekerjaan dan menggabungkannya dengan string

Saat Anda perlu menjalankan ratusan atau ribuan pekerjaan terkait (misalnya, mengimpor CSV berukuran besar secara bertahap, memproses file secara berkelompok, membersihkan data, dll.), disarankan untuk menggunakan fungsi batch Laravel .

Aliran dasar:

  • Membuat tabel job_batches dengan php artisan queue:batches-table && php artisan migrate.
  • Tandai Pekerjaan yang akan menjadi bagian dari kelompok dengan sifat tersebut Batchable.
  • Usar Bus::batch() untuk mengirim serangkaian Pekerjaan, dengan panggilan balik then, catch y finally.
  • Akses batch dari setiap Pekerjaan dengan $this->batch() dan periksa apakah sudah dibatalkan.
  • Kemungkinan untuk menambahkan lebih banyak Pekerjaan ke batch yang sedang berlangsung dengan $this->batch()->add().

Batch terintegrasi dengan baik dengan chain : Anda dapat memiliki chain di dalam satu batch atau batch sebagai elemen dari chain yang lebih besar. Ini sangat berguna ketika Anda ingin beberapa chain berjalan "secara paralel" dan memicu sesuatu ketika semuanya telah selesai.

Eksekusi, prioritas, dan penempatan pekerja

Semua keajaiban antrian terjadi karena Anda memiliki satu atau lebih pekerja menjalankan perintah queue:work (o queue:listen(meskipun yang terakhir kurang efisien). Proses-proses ini adalah daemon yang berjalan lama yang mendengarkan antreannya masing-masing.

Pilihan utama dari queue:work:

  • Koneksi: php artisan queue:work redis, queue:work database, Dll
  • Colas: --queue=high,default,low untuk memprioritaskan.
  • -sebelas: memproses satu pekerjaan dan keluar.
  • –pekerjaan maksimal: memproses X pekerjaan dan mengakhirinya (untuk memulai ulang pekerja secara berkala dan mengosongkan memori).
  • –waktu maksimal: proses selama N detik lalu keluar.
  • -tidur: detik menunggu saat tidak ada pekerjaan yang tersedia.
  • –berhenti-ketika-kosong: mengosongkan antrean dan menutup dengan bersih (idealnya di lingkungan Docker atau pekerjaan satu kali).
  • –waktu habis: detik batas waktu per pekerjaan, seperti yang kami sebutkan sebelumnya.
  • -memaksa: untuk memproses pekerjaan bahkan jika aplikasi dalam mode pemeliharaan.

Karena proses-proses ini berjalan lama, dalam lingkungan produksi, monitor proses seperti Supervisor (pada Linux) hampir selalu digunakan untuk memulai X worker, memulai ulang jika terjadi crash, dan mengelola log. Blok konfigurasi Supervisor yang umum untuk Laravel mendefinisikan:

  • Command dengan php artisan queue:work ... konkret.
  • numprocs untuk menunjukkan berapa banyak pekerja yang akan diluncurkan secara paralel.
  • Jalur log, pengguna, mulai ulang otomatis, dll.

Menjeda dan melanjutkan antrian di Laravel

Mari kita bahas hal yang seringkali penting dalam pemeliharaan: bagaimana cara menjeda pekerja antrian tanpa menghentikannya secara tiba-tiba dan tanpa meninggalkan pekerjaan yang belum selesai. Laravel menawarkan beberapa mekanisme, beberapa lebih baru, beberapa klasik, untuk mengontrol hal ini.

Jeda: antrian:jeda dan sinyal interupsi

Pada versi terbaru, Laravel menambahkan perintah khusus untuk menghentikan sementara dan melanjutkan eksekusi worker:

  • php artisan queue:pause: memberi tahu sistem agar berhenti mengambil pekerjaan baru, tetapi membiarkan pekerjaan yang sedang berlangsung selesai.
  • php artisan queue:continue: melanjutkan pemrosesan pekerjaan baru dari titik yang ditinggalkannya.
  Menguasai Pengujian Unit Perangkat Lunak

Perintah-perintah ini bekerja dengan mengirimkan sinyal ke worker melalui mekanisme caching yang digunakan Laravel secara internal. Itulah mengapa penting untuk memiliki driver cache yang dikonfigurasi dengan benar (memcached, redis, database, file, dll.) meskipun antrian cache Anda sebenarnya adalah sesuatu yang lain.

Penting: Menjeda antrean atau pekerja tidak membatalkan atau menghapus pekerjaan yang sudah ada dalam antrean ; hal itu hanya mencegah lebih banyak pekerjaan dikeluarkan dari antrean selama jeda berlangsung.

Polling gangguan dan dampaknya terhadap kinerja

Setiap kali worker menyelesaikan tugasnya, Laravel memeriksa cache untuk sinyal restart, pause, atau continue . Biayanya sangat kecil, tetapi tetap ada. Jika Anda sangat fokus pada performa dan tahu bahwa Anda tidak perlu melakukan pause atau restart worker dari perintah, Anda dapat menonaktifkan polling ini dengan memanggil:

Queue::withoutInterruptionPolling();

Atau bahkan menyesuaikan properti statis Illuminate\Queue\Worker untuk menonaktifkan sentuhan tertentu ($dapatdimulai ulang, $pausableNamun, jika Anda melakukan ini dan kemudian mencoba menggunakan queue:pause o queue:restartpara pekerja Mereka tidak akan mengetahuinyaIni adalah keputusan desain yang harus dipertimbangkan secara cermat.

Jeda secara manual dengan Supervisor atau Docker

Selain perintah Laravel sendiri , di lingkungan produksi, proses sering kali "dijeda" secara tidak langsung:

  • Menghentikan program di Supervisor (supervisorctl stop laravel-worker:*), yang membunuh atau menghentikan pekerja.
  • Menggunakan –berhenti-ketika-kosong dalam penempatan untuk membiarkan pekerja menyelesaikan apa yang ada dalam antrean dan kemudian mematikannya.
  • Di Docker, membiarkan kontainer memproses dengan --stop-when-empty dan kemudian mati.

Beda dengan queue:pause Dengan menghentikan proses sepenuhnya, Anda akan berhenti memproses pekerjaan hingga pekerja memulai kembali. jeda internal Anda dapat menyimpan proses dalam memori, menunggu perintah continueIni berguna untuk penerapan roll-back cepat atau periode pemeliharaan singkat.

Transaksi basis data dan after_commit

Kesalahan klasik: mengirimkan tugas dalam transaksi basis data . Jika Anda tidak hati-hati, pekerja mungkin mengeksekusi tugas sebelum commit dilakukan, dan model atau data yang Anda harapkan mungkin belum ada di basis data.

Untuk menghindari tarian ini, Anda punya dua pilihan:

  • Mengaktifkan 'after_commit' => true dalam konfigurasi koneksi antrean. Dengan demikian, setiap Pekerjaan yang dikirim dalam suatu transaksi ditunda secara internal hingga dikonfirmasi.
  • Gunakan metode per pekerjaan afterCommit() o beforeCommit() saat pengiriman, untuk memaksa perilaku hanya pada Pekerjaan tertentu.

Jika transaksi dibatalkan, pekerjaan yang dikirim selama transaksi tersebut akan dibuang tanpa pernah masuk ke dalam antrian, yang justru merupakan hal yang diinginkan untuk menjaga konsistensi.

Pemantauan, pembersihan antrean, dan pengujian

Setelah antrean berjalan dengan lancar, tidak cukup hanya membuat Job dan melupakannya; Anda harus memantau dan menguji bagaimana semuanya berperilaku.

Alat dan perintah yang berguna:

  • queue:clear untuk mengosongkan antrean tertentu (SQS, Redis, database).
  • queue:monitor untuk memantau jumlah pekerjaan dalam antrian tertentu dan memicu peristiwa tersebut QueueBusy jika melampaui ambang batas.
  • Acara Pekerjaan sebagai Queue::before, Queue::after, Queue::looping y Queue::failing untuk mengaitkan logika khusus (log, metrik, pengembalian, dsb.).
  • Palsu dalam pengujian menggunakan Queue::fake() y Bus::fake() untuk memverifikasi bahwa Pekerjaan, string atau batch telah dikirim tanpa benar-benar mengeksekusinya.

Dalam pengujian, Anda dapat menyatakan hal-hal seperti "Pekerjaan ini telah dimasukkan ke dalam antrian sebanyak X kali" , "rantai dengan Pekerjaan-pekerjaan ini telah dikirim dalam urutan ini" atau "tidak ada Pekerjaan tertentu yang dimasukkan ke dalam antrian", yang memberikan banyak keamanan dalam alur kerja yang kompleks.

Dengan seluruh ekosistem ini—pengemudi seperti Redis atau SQS, pekerjaan yang dirancang dengan baik, middleware untuk fine-tuning, batch, rantai, konfigurasi percobaan ulang, pekerja yang dikelola Supervisor, dan perintah seperti queue:pause y queue:continue— Laravel memungkinkan Anda menguasai pemrosesan latar belakang hingga ke milimeter, dari pengiriman email biasa hingga arsitektur antrean terdistribusi dengan failover, memastikan aplikasi Anda terus merespons dengan cepat pada lapisan HTTP sementara pekerjaan berat dilakukan di bawahnya tanpa memblokir pengguna.

Kerangka Laravel
Artikel terkait:
Framework Laravel yang Kuat