- Laravel menawarkan API baris gilir bersatu dengan berbilang pemacu (pangkalan data, Redis, SQS…) dan pemisahan antara sambungan dan baris gilir logik.
- Pekerjaan membenarkan tugas tugas berat dialihkan ke latar belakang, dengan sokongan untuk model bersiri, perisian tengah, kerja sekali sahaja, penyulitan, kelompok dan rentetan.
- Pekerja diuruskan dengan baris gilir:kerja, Penyelia dan arahan seperti baris gilir:jeda/gilir:sambung, mengawal percubaan semula, tamat masa dan keutamaan.
- Terdapat ekosistem lengkap untuk kegagalan, pemantauan dan ujian (failed_jobs, queue:retry, queue:monitor, Queue::fake) yang menjadikan giliran boleh dipercayai dalam pengeluaran.
Bekerja dengan barisan dalam Laravel hampir wajib dalam mana-mana projek yang agak serius: menghantar e-mel, memproses fail CSV, menjana PDF, mengubah saiz imej, memanggil API luaran… Jika semua itu dilakukan dalam permintaan HTTP utama, laman web menjadi perlahan, 500 ralat muncul, dan pengguna akhirnya hanya merenung skrin kosong dengan terdesak.
Berita baiknya ialah Laravel menawarkan infrastruktur giliran yang berkuasa dan fleksibel yang membolehkan anda mewakilkan kerja berat kepada proses latar belakang, mengurusnya mengikut keutamaan, mengumpulkannya ke dalam kelompok, memantaunya, mencubanya semula apabila gagal, dan juga menjeda pekerja buat sementara waktu untuk penyelenggaraan. Mari kita lihat dengan teliti (dan jangan tinggalkan apa-apa) tentang cara untuk memanfaatkannya sepenuhnya, termasuk cara menjeda, menyambung semula dan mengawal kelakuannya dalam pengeluaran.
Konsep asas: sambungan, baris gilir dan pemandu
Dalam Laravel, sebelum menjeda apa-apa, anda perlu memahami perbezaan antara sambungan beratur dan beratur sendiri. Dalam config/queue.php anda mempunyai tatasusunan connections tempat anda menentukan setiap hujung belakang: pangkalan data, redis, beanstalkd, sqs, sync, null, failover, rabbitmq (jika anda menambahnya), dsb.
Setiap sambungan boleh mempunyai beberapa barisan logik (nama seperti default, emails, high, low, importsAtribut queue Setiap sambungan menunjukkan baris gilir lalai di mana kerja akan pergi jika tiada yang lain ditentukan. onQueue()Dengan cara ini anda boleh melakukan perkara seperti:
- Beratur cepat untuk e-mel atau transaksi pendek.
- Satu lagi keutamaan rendah untuk tugasan yang panjang seperti memproses video atau laporan besar.
- Baris gilir dibahagikan mengikut jenis tugas:
imports,notificaciones,reportes, Dll
Apabila anda melancarkan pekerja dengan php artisan queue:workSecara lalai, ia mendengar baris gilir yang ditentukan sebagai lalai pada sambungan yang dipilih. Jika anda ingin memberi keutamaan, anda boleh melepasi berbilang baris gilir yang dipisahkan koma:
php artisan queue:work redis --queue=high,default,low
Dengan cara ini, pekerja memproses high dahulu , kemudian default , dan hanya kemudian low , yang penting apabila sistem dimuatkan dan anda tidak mahu laporan 30 minit menyekat e-mel berprioriti tinggi.
Pemandu baris gilir dan prasyarat
Laravel menawarkan API terpadu untuk beberapa pemacu giliran , tetapi setiap satunya mempunyai ciri dan kebergantungan khusus. Memilih pemacu yang betul adalah penting sebelum membincangkan tentang pekerja yang dijeda.
Pangkalan data pemandu
Pemandu itu pangkalan data Ia menyimpan kerja dalam jadual SQL (biasanya jobsIa mudah disediakan dan sesuai untuk projek kecil atau persekitaran pembangunan yang anda tidak mahu bermain-main dengan Redis atau SQS.
Langkah asas:
- Hasilkan migrasi:
php artisan queue:table(atau dalam versi yang lebih baru, ia datang sebagaicreate_jobs_tablelalai). - Jalankan migrasi:
php artisan migrate. - Konfigurasikan QUEUE_CONNECTION=pangkalan data dalam
.envdan sahkan dalamconfig/queue.phpbahawa'default' => env('QUEUE_CONNECTION','database').
Ia mudah dan cukup mantap, tetapi dengan banyak barisan dan banyak trafik, ia boleh menjadi kesesakan , kerana semuanya melalui pangkalan data hubungan yang sama.
Pemandu Redis
Pemacu Redis ialah pemacu standard dalam pengeluaran. Ia pantas, menyokong ciri-ciri canggih (penguncian, pengehadan kadar, kunci atomik, Horizon, dll.), dan berskala dengan sangat baik.
Puntos penting:
- Anda perlu mengkonfigurasi sambungan Redis dalam
config/database.php. - Pilihannya
serializerycompressiondaripada Redis Mereka tidak serasi dengan pemandu giliran. - Jika anda menggunakannya Redis ClusterNama baris gilir mesti mempunyai teg cincang, contohnya
{default}supaya semua kunci dalam baris gilir itu jatuh ke dalam slot yang sama. - Pilihan
block_forIa membenarkan pekerja menyekat semasa menunggu kerja selama beberapa saat, bukannya mengundi secara berterusan: menjimatkan CPU dan mengurangkan pertanyaan kepada pelayan Redis.
Sebagai contoh:
'redis' => ,
Jika anda meletakkan blok_untuk = 0Pekerja tetap disekat selama-lamanya sehingga kerja tersedia, sesuatu yang perlu diingat jika anda mahu ia bertindak balas dengan cepat kepada isyarat seperti SIGTERM atau jeda arahan.
Pemacu lain: SQS, Beanstalkd, null, failover…
Selain pangkalan data dan redis, Laravel menyokong sistem lain :
- Amazon SQSBarisan gilir terurus pada AWS, dengan sokongan untuk FIFOKumpulan mesej, penyahduplikasian dan tetapan keterlihatan lanjutan. Memerlukan SDK.
aws/aws-sdk-php. - BeanstalkdSangat cepat dan mudah, menggunakan pakej
pda/pheanstalk. - menyegerakkan: menjalankan tugas segera dalam proses yang sama. Berguna dalam pembangunan atau ujian, tetapi dalam pengeluaran ia boleh dikatakan seperti tidak menggunakan baris gilir sama sekali.
- sifar: Membuang kerja sebaik sahaja ia "dihantar". Digunakan untuk melumpuhkan sepenuhnya sistem beratur.
- failoverIni membolehkan anda mengkonfigurasi berbilang sambungan, dan jika sambungan utama gagal, Laravel cuba untuk menolak kerja ke sambungan seterusnya dalam senarai. Sesuai untuk persekitaran di mana ketersediaan yang tinggi adalah kritikal.
Pada tahap menjeda dan menyambung semula pekerja, logiknya hampir sama tanpa mengira pemacu, kerana ia diuruskan daripada arahan Artisan dan kelas Pekerja , bukan daripada bahagian belakang barisan.
Penciptaan kerja dan siri model
Un Kerja Dalam Laravel, ia hanyalah kelas yang merangkum tugasan untuk dilaksanakan dalam baris gilir. Ia biasanya dijana dengan Artisan dan disimpan dalam app/Jobs.
Untuk mencipta satu:
php artisan make:job ProcessPodcast
Kelas yang dihasilkan melaksanakan ShouldQueue dan biasanya menggunakan sifat Dispatchable, InteractsWithQueue, Queueable y SerializesModelsHati berada dalam kaedah handle()yang dilakukan oleh pekerja apabila pekerjaan itu tiba.
Satu ciri yang sangat berkuasa ialah penyirian automatik model Eloquent . Jika anda menerima model dalam pembina Kerja, Laravel tidak menambah keseluruhan objek pada baris gilir, hanya pengecamnya. Apabila kerja diproses, ia akan membina semula model daripada pangkalan data dengan perhubungannya dimuatkan.
Contoh biasa (dalam pseudokod, untuk mengelakkan pengulangannya secara verbatim):
- Pembina menerima Podcast $podcast.
- sifat
SerializesModelsIa bertanggungjawab untuk menyimpan ID. - En
handle(AudioProcessor $processor)Anda melakukan kerja keras (memproses audio, contohnya).
Jika anda tidak mahu perhubungan dalam model bersiri (jadi muatannya tidak besar), anda boleh menggunakan $model->withoutRelations() atau dalam PHP 8 atribut # pada harta yang dinaikkan pangkat pembina.
Suntikan kebergantungan dalam kaedah pemegang
Kelebihan lain ialah anda boleh menyuntik perkhidmatan terus ke dalam kaedah pemegang (seolah-olah ia adalah pengawal), kerana Laravel juga menggunakan bekas perkhidmatan dalam Jobs. Sebagai contoh, anda boleh meminta a AudioProcessorPelanggan HTTP, repositori, dsb., dan rangka kerja menguruskan penyelesaiannya.
Jika anda memerlukan kawalan ultra halus terhadap apa yang dipanggil handleanda boleh gunakan Container::bindMethod() dalam pembekal perkhidmatan dan tentukan sendiri logik suntikan, tetapi dalam kebanyakan kes, tidak perlu merumitkan banyak perkara.
Perisian Tengah Kerja
Sama seperti laluan mempunyai perisian tengah, Jobs juga boleh mempunyai perisian tengah tertentu yang dijalankan sebelum dan selepas kerja. Ini sangat mengurangkan kod berulang dalam kaedah handle() dan ia amat berguna untuk:
- Mengehadkan kadar dengan Redis.
- mengelakkan bertindih karya yang menyentuh sumber yang sama.
- Pengecualian biasa untuk API yang tidak stabil.
- Ponteng kerja dalam keadaan tertentu (
Skipperisian tengah).
Middleware biasanya diletakkan di dalam app/Jobs/Middleware dan dikembalikan daripada kaedah middleware() Daripada Ayub. Contoh konseptual:
public function middleware(): array { return ;
Jenis pekerjaan istimewa: unik, disulitkan dan dikunci
Laravel membolehkan anda menandakan kerja tertentu sebagai unik untuk memastikan bahawa tiada dua kejadian yang sama akan beratur pada masa yang sama. Ini dicapai dengan melaksanakan antara muka ShouldBeUnique o ShouldBeUniqueUntilProcessingdan menyokong penentuan kunci uniqueId() dan satu masa uniqueFor.
Ini sesuai untuk perkara seperti:
- Kira semula indeks carian produk: sekali sahaja setiap produk sehingga selesai.
- Penyegerakan dengan perkhidmatan luaran yang tidak membenarkan permintaan serentak untuk sumber yang sama.
Di bawahnya, Laravel menggunakan a kunci atom cache (Redis, memcached, pangkalan data, dll.). Anda juga boleh memilih pemacu cache untuk kunci itu uniqueVia().
Di samping itu, terdapat antara muka ShouldBeEncrypted, yang mana anda menunjukkan bahawa Ayub yang lengkap adalah Masukkan kod anda sebelum memasuki baris gilirSangat berguna apabila menghantar data sensitif dan anda tidak mahu ia bergerak dalam teks biasa melalui Redis, SQS atau pangkalan data.
Hantar, tangguh dan laksanakan kerja dalam mod yang berbeza
Setelah tugas anda ditentukan, anda melancarkannya dengan Job::dispatch() daripada pengawal, pendengar acara, arahan Artisan, atau juga penutupan. Parameter yang anda lalui dispatch Mereka pergi terus kepada pembina Ayub.
Variasi yang menarik:
dispatchIf()ydispatchUnless()untuk keadaan penghantaran dalam satu baris.delay()supaya kerja tidak dapat diproses sehingga tarikh/masa tertentu.dispatchAfterResponse()oafterResponse()endispatch()Penutupan, yang menangguhkan pelaksanaan sehingga respons HTTP telah dihantar, tetapi dalam proses PHP yang sama.dispatchSync()untuk menjalankan Kerja secara serentak (tanpa melalui baris gilir) tetapi menggunakan semula kelas yang sama.- Sambungan khas seperti
deferredobackgrounduntuk melaksanakan selepas respons, dalam proses yang sama atau dalam proses PHP baharu.
Akhir sekali, anda boleh menentukan sambungan dan baris gilir dengan kaedah berantai onConnection() y onQueue(), sama ada semasa menghantar atau dalam pembina Kerja.
Kawalan halus: cuba semula, mundur, tamat masa dan pengendalian ralat
Sebahagian besar daripada bekerja dengan barisan dalam Laravel adalah menentukan berapa kali untuk mencuba semula sesuatu kerja , berapa lama untuk menunggu antara percubaan dan bila untuk menganggapnya sebagai kegagalan.
Pilihan yang ada:
--triesenqueue:workuntuk menetapkan bilangan maksimum percubaan untuk semua pekerjaan pekerja itu (melainkan Pekerjaan menentukan sendiri)$triesotries()).$triesatau kaedahtries()dalam kelas Pekerjaan untuk kawalan setiap Pekerjaan.retryUntil()untuk mengatakan: "cuba lagi seperti yang anda mahu sehingga kali ini, selepas itu, kegagalan." Jika bertepatan dengantries, perintahretryUntil.$maxExceptionsuntuk memotong apabila masalah itu disebabkan oleh pengecualian berulang yang tidak dikendalikan.$timeouto--timeoutuntuk menunjukkan berapa saat Job boleh dijalankan sebelum pekerja membunuh proses kanak-kanak.$failOnTimeoutuntuk menandakan kerja sebagai gagal sekiranya tamat masa.$backoffkaedahbackoff()untuk menentukan berapa lama menunggu antara percubaan semula, walaupun dengan nilai eksponen.
Jika sesuatu kerja melemparkan pengecualian yang tidak ditangkap, Laravel akan... dilepaskan kembali ke ekor sehingga percubaan yang dikonfigurasikan habis. Anda boleh mengawal ini secara manual dengan release($segundos) o fail($exception) apabila anda mahu dengan sengaja menandakan kerja sebagai gagal.
Kerja gagal, failed_jobs jadual dan pemangkasan
Apabila Ayub telah meletihkan percubaannya, dia akan dipertimbangkan kerja gagal dan Laravel memasukkannya ke dalam jadual failed_jobs (atau dalam DynamoDB jika anda mengkonfigurasinya dengan cara itu). Jadual itu menyimpan UUID, sambungan, baris gilir, muatan kerja dan pengecualian yang dilemparkan.
Perintah berguna:
php artisan queue:faileduntuk menyenaraikan yang gagal.php artisan queue:retry <id|all>untuk mencuba mereka lagi.php artisan queue:forget <id>untuk memadam satu.php artisan queue:flushuntuk memadam semua (dengan pilihan untuk jam dalam versi yang lebih baharu).php artisan queue:prune-failed --hours=48untuk memangkas rekod lama secara automatik.
Dalam Pekerjaan anda boleh menentukan kaedah failed(Throwable $exception) Untuk pembersihan tambahan: maklumkan pengguna, kembalikan tindakan separa, tulis log khusus, dsb. Ambil perhatian bahawa kejadian baharu Kerja dibuat untuk memanggil failed()Oleh itu, jangan bergantung pada perubahan harta yang dibuat dalam handle().
Kelompok kerja: kelompok kerja dan menggabungkannya dengan rentetan
Apabila anda perlu melancarkan ratusan atau ribuan kerja berkaitan (contohnya, mengimport CSV gergasi dalam ketulan, memproses fail dalam kelompok, membersihkan data, dll.), adalah dinasihatkan untuk menggunakan fungsi kelompok Laravel .
Aliran asas:
- buat jadual
job_batchesdenganphp artisan queue:batches-table && php artisan migrate. - Tandai Pekerjaan yang akan menjadi sebahagian daripada kelompok dengan ciri tersebut
Batchable. - Gunakan
Bus::batch()untuk menghantar satu set Pekerjaan, dengan panggilan balikthen,catchyfinally. - Akses kumpulan daripada setiap Kerja dengan
$this->batch()dan semak sama ada ia dibatalkan. - Kemungkinan untuk menambah lebih banyak Pekerjaan pada kumpulan yang sedang berjalan dengan
$this->batch()->add().
Kelompok berintegrasi dengan indah dengan rantai : anda boleh mempunyai rantai dalam kelompok atau kelompok sebagai elemen rantai yang lebih besar. Ini amat berguna apabila anda mahu berbilang rantai berjalan "selari" dan mencetuskan sesuatu apabila semuanya selesai.
Pelaksanaan pekerja, keutamaan dan penempatan
Semua keajaiban baris gilir berlaku kerana anda ada seorang atau lebih pekerja menjalankan perintah queue:work (o queue:listen(walaupun yang terakhir kurang cekap). Proses ini adalah daemon jangka panjang yang mendengar baris gilir masing-masing.
Pilihan utama bagi queue:work:
- conexión:
php artisan queue:work redis,queue:work database, Dll - Kola:
--queue=high,default,lowuntuk diutamakan. - -sebelas: memproses satu kerja dan keluar.
- –maksimum-pekerjaan: memproses kerja X dan ditamatkan (untuk memulakan semula pekerja secara berkala dan mengosongkan ingatan).
- –masa maksimum: proses selama N saat dan kemudian keluar.
- –tidur: saat menunggu apabila tiada kerja tersedia.
- –berhenti-bila-kosong: mengosongkan baris gilir dan menutup dengan bersih (sesuai dalam persekitaran Docker atau kerja sekali sahaja).
- – tamat masa: saat tamat masa setiap kerja, seperti yang kami nyatakan sebelum ini.
- -Force: untuk memproses kerja walaupun apl berada dalam mod penyelenggaraan.
Oleh kerana proses ini berjalan lama, dalam pengeluaran, monitor proses seperti Supervisor (pada Linux) hampir selalu digunakan untuk memulakan pekerja X, memulakan semula mereka jika mereka ranap, dan mengurus log. Blok konfigurasi Supervisor biasa untuk Laravel mentakrifkan:
- arahan dengan
php artisan queue:work ...konkrit. - numprocs untuk menunjukkan bilangan pekerja yang perlu dilancarkan secara selari.
- Log laluan, pengguna, mula semula automatik, dsb.
Menjeda dan menyambung semula baris gilir dalam Laravel
Mari kita lihat apa yang sering penting dalam penyelenggaraan: cara menjeda pekerja barisan tanpa menghentikan mereka secara tiba-tiba dan tanpa meninggalkan kerja yang belum selesai. Laravel menawarkan beberapa mekanisme, ada yang lebih baharu, ada yang klasik, untuk mengawalnya.
Jeda: giliran:jeda dan isyarat sampuk
Dalam versi terkini, Laravel menambah arahan khusus untuk menjeda dan menyambung semula pelaksanaan pekerja:
php artisan queue:pause: memberitahu sistem untuk berhenti mengambil kerja baharu, tetapi membiarkan kerja yang sedang berjalan selesai.php artisan queue:continue: menyambung semula memproses pekerjaan baharu dari tempat ia berhenti.
Arahan ini berfungsi dengan menghantar isyarat kepada pekerja melalui mekanisme caching yang digunakan oleh Laravel secara dalaman. Itulah sebabnya penting untuk mempunyai pemacu cache yang dikonfigurasikan dengan betul (memcached, redis, pangkalan data, fail, dll.) walaupun giliran cache sebenar anda adalah sesuatu yang lain.
Penting: Menjeda giliran atau pekerja tidak membatalkan atau memadamkan kerja yang telah beratur ; ia hanya menghalang lebih banyak kerja daripada dialih keluar daripada giliran semasa jeda berlangsung.
Tinjauan gangguan dan kesan ke atas prestasi
Setiap kali pekerja menyelesaikan kerja, Laravel menyemak cache untuk isyarat mula semula, jeda atau teruskan . Ini mempunyai kos yang boleh diabaikan, tetapi ia wujud. Jika anda sangat fokus pada prestasi dan tahu anda tidak perlu menjeda atau memulakan semula pekerja daripada arahan, anda boleh melumpuhkan tinjauan pendapat ini dengan memanggil:
Queue::withoutInterruptionPolling();
Atau laraskan sifat statik bagi Illuminate\Queue\Worker untuk melumpuhkan sentuhan tertentu ($boleh dimulakan, $boleh dijedaWalau bagaimanapun, jika anda melakukan ini dan kemudian cuba gunakan queue:pause o queue:restartpara pekerja Mereka tidak akan tahuIa adalah keputusan reka bentuk yang harus dipertimbangkan dengan teliti.
Jeda secara manual dengan Penyelia atau Docker
Selain arahan Laravel sendiri , dalam persekitaran pengeluaran, proses sering "dijeda" secara tidak langsung:
- Menghentikan program dalam Penyelia (
supervisorctl stop laravel-worker:*), yang membunuh atau menghentikan pekerja. - Dengan Menggunakan –berhenti-bila-kosong dalam penempatan untuk membiarkan pekerja menyelesaikan apa yang ada dalam baris gilir dan kemudian ditutup.
- Dalam Docker, membiarkan bekas memproses dengan
--stop-when-emptydan kemudian ia dimatikan.
Perbezaan dengan queue:pause Dengan menghentikan sepenuhnya proses, anda akan berhenti memproses kerja sehingga pekerja dimulakan semula. jeda dalaman Anda boleh menyimpan proses dalam ingatan, menunggu arahan continueIni berguna untuk penggunaan roll-back yang cepat atau tempoh penyelenggaraan yang singkat.
Transaksi pangkalan data dan after_commit
Kesilapan klasik: menghantar kerja dalam transaksi pangkalan data . Jika anda tidak berhati-hati, pekerja mungkin melaksanakan kerja sebelum komit dibuat dan model atau data yang anda jangkakan mungkin belum berada dalam pangkalan data.
Untuk mengelakkan tarian ini, anda mempunyai dua pilihan:
- Mengaktifkan
'after_commit' => truedalam konfigurasi sambungan baris gilir. Oleh itu, sebarang Kerja yang dihantar dalam urus niaga ditangguhkan secara dalaman sehingga ia disahkan. - Gunakan kaedah setiap kerja
afterCommit()obeforeCommit()apabila menghantar, untuk memaksa tingkah laku hanya dalam Pekerjaan tertentu.
Jika transaksi diterbalikkan, kerja yang dihantar semasa transaksi tersebut akan dibuang tanpa perlu memasuki barisan, yang mana inilah yang biasanya dikehendaki untuk mengekalkan konsistensi.
Pemantauan, pembersihan baris gilir, dan ujian
Sebaik sahaja anda telah beratur dan menjalankan tugas dengan bersungguh-sungguh, tidak mencukupi untuk hanya membuang Jobs dan melupakannya; anda harus memantau dan menguji bagaimana semuanya berfungsi.
Alat dan arahan yang berguna:
queue:clearuntuk mengosongkan baris gilir tertentu (SQS, Redis, pangkalan data).queue:monitoruntuk memantau bilangan kerja dalam baris gilir tertentu dan mencetuskan acaraQueueBusyjika mereka melebihi ambang.- Acara Kerja sebagai
Queue::before,Queue::after,Queue::loopingyQueue::failinguntuk mengaitkan logik tersuai (log, metrik, rollback, dsb.). - Palsu dalam ujian menggunakan
Queue::fake()yBus::fake()untuk mengesahkan bahawa Pekerjaan, rentetan atau kelompok telah dihantar tanpa benar-benar melaksanakannya.
Dalam ujian, anda boleh menyatakan perkara seperti "Kerja ini telah diantrekan X kali" , "rantaian dengan Kerja ini telah dihantar dalam susunan ini" atau "tiada Kerja tertentu telah diantrekan", yang menyediakan banyak keselamatan dalam aliran kompleks.
Dengan keseluruhan ekosistem ini—pemacu seperti Redis atau SQS, kerja yang direka bentuk dengan baik, perisian tengah untuk penalaan halus, kelompok, rantai, konfigurasi cuba semula, pekerja yang diuruskan Penyelia dan arahan seperti queue:pause y queue:continue— Laravel membolehkan anda menguasai pemprosesan latar belakang hingga ke milimeter, daripada penghantaran e-mel biasa kepada seni bina baris gilir yang diedarkan dengan failover, memastikan aplikasi anda terus bertindak balas dengan cepat pada lapisan HTTP sementara kerja berat sedang dilakukan di bawah tanpa menyekat pengguna.