Как да паузирате и контролирате опашки в Laravel стъпка по стъпка

Последна актуализация: 5 декември 2025
Автор: TecnoDigital
  • Laravel предлага унифициран API за опашки с множество драйвери (база данни, Redis, SQS…) и разделяне между връзки и логически опашки.
  • Задачите позволяват преместването на тежки задачи на заден план, с поддръжка за сериализиране на модели, междинен софтуер, еднократни задания, криптиране, партиди и низове.
  • Работниците се управляват с queue:work, Supervisor и команди като queue:pause/queue:continue, контролиращи повторните опити, времето за изчакване и приоритетите.
  • Съществува цялостна екосистема за откази, наблюдение и тестване (failed_jobs, queue:retry, queue:monitor, Queue::fake), която прави опашките надеждни в производствения процес.

Управление на опашки в Laravel

Работата с опашки в Laravel е почти задължителна във всеки поне малко сериозен проект: изпращане на имейли, обработка на CSV файлове, генериране на PDF файлове, преоразмеряване на изображения, извикване на външни API... Ако всичко това се направи в основната HTTP заявка, уебсайтът става бавен, появяват се 500 грешки и потребителят отчаяно се взира в празен екран.

Добрата новина е, че Laravel предлага мощна и гъвкава инфраструктура за опашки , която ви позволява да делегирате тежка работа на фонови процеси, да ги управлявате по приоритет, да ги групирате в партиди, да ги наблюдавате, да ги опитвате отново, когато се провалят, и дори временно да поставяте работните процеси на пауза за поддръжка. Нека разгледаме отблизо (и да не пропускаме нищо) как да извлечете максимума от него, включително как да го поставите на пауза, да го възобновите и да контролирате поведението му в продукционна среда.

Основни понятия: връзки, опашки и драйвери

В Laravel, преди да поставите каквото и да било на пауза, трябва да разберете разликата между връзки към опашки и самите опашки, En config/queue.php имате масив connections където дефинирате всеки бекенд: база данни, redis, beanstalkd, sqs, синхронизация, null, превключване при срив, rabbitmq (ако го добавите) и т.н.

Всяка връзка може да има няколко логически опашки (имена като default, emails, high, low, importsАтрибутът queue Всяка връзка показва коя е опашката по подразбиране, където ще отиват задачите, ако не е посочена друга. onQueue()По този начин можете да правите неща като:

  • Бърза опашка за имейли или кратки транзакции.
  • Друг нисък приоритет за дълги задачи, като например обработка на видеоклипове или големи отчети.
  • Опашки, сегментирани по тип задача: imports, notificaciones, reportesИ др

Когато стартирате работника с php artisan queue:workПо подразбиране, той слуша опашката, посочена като по подразбиране на избраната връзка. Ако искате да приоритизирате, можете да подадете няколко опашки, разделени със запетаи:

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

По този начин, работникът обработва първо high , след това default и едва след това low , което е от решаващо значение, когато системата е заредена и не искате 30-минутен отчет да блокира имейли с висок приоритет.

Драйвери за опашки и предварителни изисквания

Laravel предлага унифициран API за няколко драйвера на опашки , но всеки от тях има свои специфични характеристики и зависимости. Изборът на правилния драйвер е от решаващо значение, преди да се обсъди паузирането на работници.

База данни с драйвери

Шофьорът база данни Съхранява задачите в SQL таблица (обикновено jobsЛесно се настройва и е идеален за малки проекти или среди за разработка, където не искате да се занимавате с Redis или SQS.

Основни стъпки:

  • Генериране на миграцията: php artisan queue:table (или в по-новите версии, той се предлага като create_jobs_table по подразбиране).
  • Изпълнете миграции: php artisan migrate.
  • конфигуриране QUEUE_CONNECTION=база_данни в .env и потвърдете в config/queue.php че 'default' => env('QUEUE_CONNECTION','database').

Удобно и достатъчно стабилно е, но с много опашки и голям трафик може да се превърне в пречка , тъй като всичко преминава през една и съща релационна база данни.

Драйвер Redis

Драйверът на Redis е стандартният работен кон в продакшън среда. Той е бърз, поддържа разширени функции (заключване, ограничаване на скоростта, атомни заключвания, Horizon и др.) и се мащабира много добре.

Важни моменти:

  • Трябва да конфигурирате Redis връзката в config/database.php.
  • Опциите serializer y compression от Редис Те не са съвместими с водача на опашката.
  • Ако използвате Redis клъстерИмената на опашките трябва да имат хаштаг, например {default}така че всички ключове в тази опашка да попаднат в един и същ слот.
  • Опцията block_for Това позволява на работника да блокира, докато чака задачи за няколко секунди, вместо непрекъснато да извършва запитвания: спестява процесор и намалява заявките към Redis сървъра.

Например:

'redis' => ,

Ако сложите блок_за = 0Работникът остава блокиран за неопределено време, докато не се освободи работа, нещо, което трябва да се има предвид, ако искате той да реагира бързо на сигнали като SIGTERM или команди за пауза.

Други драйвери: SQS, Beanstalkd, null, failover…

В допълнение към бази данни и Redis, Laravel поддържа и други системи :

  • Amazon SQSУправлявани опашки в AWS, с поддръжка за FIFOГрупи съобщения, дедупликация и разширени настройки за видимост. Изисква SDK. aws/aws-sdk-php.
  • Бобено стъблоМного бързо и лесно, използвайки пакета pda/pheanstalk.
  • синхронизирате: изпълнява задачите inmediatamente в един и същ процес. Полезно при разработка или тестване, но в производство е все едно изобщо да не се използват опашки.
  • нула: Изхвърля задачите веднага щом бъдат „изпратени“. Използва се за пълно деактивиране на системата за опашки.
  • сривТова ви позволява да конфигурирате множество връзки и ако основната се провали, Laravel се опитва да прехвърли задачата към следващата в списъка. Идеално за среди, където висока наличност е критично.
  Electron JS: Всичко, което трябва да знаете

На ниво паузиране и възобновяване на работните процеси, логиката е практически една и съща, независимо от драйвера, защото се управлява от командите на Artisan и класа Worker , а не от backend-а на опашката.

Създаване на задачи и сериализация на модели

Un Работа В Laravel това е просто клас, който капсулира задача, която да бъде изпълнена в опашка. Обикновено се генерира с Artisan и се запазва в app/Jobs.

За да създадете такъв:

php artisan make:job ProcessPodcast

Генерираният клас реализиране ShouldQueue и обикновено използва черти Dispatchable, InteractsWithQueue, Queueable y SerializesModelsСърцето е в метода handle()което работникът прави, когато работата пристигне.

Особено мощна функция е автоматичната сериализация на Eloquent модели . Ако приемете модел в конструктора на заданието, Laravel не добавя целия обект към опашката, а само неговия идентификатор. Когато заданието се обработи, то реконструира модела от базата данни със заредени връзки.

Типичен пример (в псевдокод, за да се избегне дословното му повтаряне):

  • Строителят получава Подкаст $podcast.
  • Чертата SerializesModels Той е отговорен за запазването на идентификационния номер.
  • En handle(AudioProcessor $processor) Вие вършите трудната работа (например обработка на аудио).

Ако не искате връзките в модела да бъдат сериализирани (така че полезният товар да не е огромен), можете да използвате $model->withoutRelations() или в PHP 8 атрибутът # върху имота, рекламиран от строителя.

Инжектиране на зависимости в метода handle

Друго предимство е, че можете инжектиране на услуги директно в метода handle (сякаш е контролер), защото Laravel също използва контейнера за услуги в Jobs. Например, можете да заявите AudioProcessorHTTP клиенти, хранилища и т.н., а рамката се грижи за разрешаването им.

Ако имате нужда от ултрафин контрол на това, което се нарича handleможете да използвате Container::bindMethod() в доставчик на услуги и сами да дефинирате логиката на инжектиране, но в повечето случаи няма нужда да усложнявате нещата толкова много.

Middleware за задачи

Точно както маршрутите имат мидълуер, така и задачите могат да имат специфичен междинен софтуер които се изпълняват преди и след задачата. Това значително намалява повтарящия се код в методите handle() и е особено полезен за:

  • Ограничаване на скоростта с Редис.
  • избегне припокрива се на произведения, които засягат един и същ ресурс.
  • Редовни изключения за нестабилни API.
  • Пропускане на задачи при определени условия (Skip междинен софтуер).

Мидълуерът обикновено се поставя в app/Jobs/Middleware и се връщат от метода middleware() От книгата Йов. Концептуален пример:

public function middleware(): array { return ;

Специални видове задачи: уникални, криптирани и заключени

Laravel ви позволява да маркирате определени задачи като уникален за да се гарантира, че нито два еднакви екземпляра не се поставят на опашка едновременно. Това се постига чрез имплементиране на интерфейса ShouldBeUnique o ShouldBeUniqueUntilProcessingи поддържа дефинирането на ключ uniqueId() и време uniqueFor.

Това е идеално за неща като:

  • Преизчислете индекса за търсене на продукт: само веднъж на продукт докато приключи.
  • Синхронизации с външни услуги, които не позволяват едновременни заявки за един и същ ресурс.

Отдолу, Laravel използва a атомна ключалка на кеш (Redis, memcached, база данни и др.). Можете също да изберете драйвера за кеш за това заключване с uniqueVia().

Освен това има интерфейс ShouldBeEncrypted, с което посочвате, че цялата работа е Въведете кода си, преди да влезете в опашкатаМного полезно, когато предавате чувствителни данни и не искате те да пътуват като обикновен текст през Redis, SQS или базата данни.

Изпращане, забавяне и изпълнение на задачи в различни режими

След като заданието ви е дефинирано, го стартирате с Job::dispatch() от контролери, слушатели на събития, команди на Artisan или дори затваряния. Параметрите, които предавате на dispatch Те отиват директно при строителя на Йов.

Интересни вариации:

  • dispatchIf() y dispatchUnless() да се кондиционира пратката в един ред.
  • delay() така че заданието да не може да бъде обработено до определена дата/час.
  • dispatchAfterResponse() o afterResponse() en dispatch() Затваряния, които отлагат изпълнението, докато HTTP отговорът не бъде изпратен, но в рамките на същия PHP процес.
  • dispatchSync() да се изпълни задачата синхронно (без да се преминава през опашката), но да се използва повторно същият клас.
  • Специални връзки, като например deferred o background да се изпълни след отговора, в същия процес или в нов PHP процес.

Накрая можете да укажете връзка и опашка с верижни методи onConnection() y onQueue(), или при изпращане, или в конструктора на задания.

Фин контрол: повторни опити, забавяне, таймаути и обработка на грешки

Голяма част от работата с опашки в Laravel е да се реши колко пъти да се опита да се извърши дадена задача , колко време да се чака между опитите и кога да се счита за неуспешна.

  Какво е front-end разработчик и какво правят?

Опциони на разположение:

  • --tries en queue:work за да зададете максималния брой опити за всички задачи на този работник (освен ако задачата не дефинира своя собствена) $tries o tries()).
  • $tries или метод tries() в класа Job за контрол на всяка задача.
  • retryUntil() да кажеш: „опитвай отново колкото искаш до този момент, след това е провал.“ Ако съвпадне с tries, команда retryUntil.
  • $maxExceptions да се прекъсне, когато проблемът се дължи на повтарящи се необработени изключения.
  • $timeout o --timeout за да се посочи колко секунди може да се изпълни дадена задача, преди работникът да прекрати дъщерния процес.
  • $failOnTimeout за да маркирате задачата като неуспешна в случай на изтичане на времето за изчакване.
  • $backoff методът backoff() за да се определи колко време да се чака между повторните опити, дори при експоненциални стойности.

Ако дадена задача хвърли неуловено изключение, Laravel ще... отново се освобождава в опашката докато конфигурираните опити не се изчерпят. Можете да контролирате това ръчно с release($segundos) o fail($exception) когато искате умишлено да маркирате дадена задача като неуспешна.

Неуспешни задачи, таблица failed_jobs и подрязване

Когато един Йов изчерпи опитите си, той започва да бъде смятан за неуспешна работа и Laravel го вмъква в таблицата failed_jobs (или в DynamoDB, ако го конфигурирате по този начин). Тази таблица съхранява UUID, връзка, опашка, полезен товар на задачата и изключението, което е било хвърлено.

Полезни команди:

  • php artisan queue:failed да изброим неуспешните.
  • php artisan queue:retry <id|all> да ги опитам отново.
  • php artisan queue:forget <id> да изтриете едно.
  • php artisan queue:flush за изтриване на всички (с опция за часове в по-новите версии).
  • php artisan queue:prune-failed --hours=48 за автоматично премахване на стари записи.

В Jobs можете да дефинирате метод failed(Throwable $exception) За допълнително почистване: уведомяване на потребителя, отмяна на частични действия, записване на специализирани лог файлове и др. Обърнете внимание, че се създава нов екземпляр на Job, който да извиква failed()Следователно, не разчитайте на промени в собствеността, направени в handle().

Пакетиране на задачи: партиди от задачи и комбинирането им с низове

Когато трябва да стартирате стотици или хиляди свързани задачи (например, импортиране на гигантски CSV файл на части, обработка на файлове на партиди, почистване на данни и т.н.), препоръчително е да използвате пакетната функционалност на Laravel .

Основен поток:

  • Създаване на таблицата job_batches с php artisan queue:batches-table && php artisan migrate.
  • Маркирайте задачите, които ще бъдат част от партиди, с характеристиката Batchable.
  • употреба Bus::batch() за изпращане на набор от задания с обратни извиквания then, catch y finally.
  • Достъп до партидата от всяка задача с $this->batch() и проверете дали е анулирано.
  • Възможност за добавяне на още задачи към текуща партида с $this->batch()->add().

Пакетите се интегрират чудесно с вериги : можете да имате вериги в рамките на един пакет или пакети като елементи на по-голяма верига. Това е особено полезно, когато искате множество вериги да работят „паралелно“ и да задействат нещо, когато всички са завършени.

Изпълнение, приоритети и разполагане на работниците

Цялата магия на опашките се случва, защото имате един или повече работници стартиране на командата queue:work (o queue:listen(въпреки че последният е по-малко ефективен). Тези процеси са дълго изпълняващи се демони, които слушат съответните си опашки.

Ключови опции на queue:work:

  • Връзка: php artisan queue:work redis, queue:work databaseИ др
  • Колас: --queue=high,default,low да се приоритизират.
  • -единадесет: обработва една задача и излиза.
  • –max-jobs: обработва X задачи и прекратява (за периодично рестартиране на работните процеси и освобождаване на памет).
  • –максимално време: обработва се за N секунди и след това се затваря.
  • –сънсекунди чакане, когато няма налични задачи.
  • –спиране-при-празен-стандарт: изпразва опашката и затваря чисто (идеално в Docker среди или еднократни задачи).
  • –таймаут: секунди време за изчакване на задача, както споменахме по-рано.
  • -Force: за обработка на задачи, дори ако приложението е в режим на поддръжка.

Тъй като тези процеси се изпълняват дълго, в продукционен режим почти винаги се използва монитор на процеси , като Supervisor (в Linux), за стартиране на X работници, рестартирането им при срив и управление на лог файлове. Типичен конфигурационен блок на Supervisor за Laravel дефинира:

  • команда с php artisan queue:work ... бетон.
  • numprocs за да се посочи колко работници да се стартират паралелно.
  • Пътища за логове, потребител, автоматични рестартирания и др.

Паузиране и възобновяване на опашки в Laravel

Нека да преминем към това, което често е важно при поддръжката: как да се поставят на пауза работници на опашки, без да се спират рязко и без да се оставят задачите недовършени. Laravel предлага няколко механизма, някои по-нови, някои класически, за контрол на това.

Пауза: опашка: сигнали за пауза и прекъсване

В последните версии Laravel добавя специфични команди за паузиране и възобновяване на изпълнението на работници:

  • php artisan queue:pause: казва на системата да спре да приема нови задачи, но да позволи на вече изпълняваните да завършат.
  • php artisan queue:continue: възобновява обработката на нови задачи от мястото, където е спряла.
  Изчисляване на фактора на инфлация на дисперсията (VIF) в C# и софтуерен дизайн

Тези команди работят, като изпращат сигнали към работните процеси чрез механизма за кеширане, който Laravel използва вътрешно. Ето защо е важно да имате правилно конфигуриран драйвер за кеш (memcached, redis, database, file и т.н.), дори ако действителната ви опашка за кеширане е нещо друго.

Важно: Паузирането на опашка или работник не отменя или изтрива вече поставени на опашка задачи ; то просто предотвратява премахването на още задачи от опашката, докато паузата трае.

Анкетиране на прекъсвания и въздействие върху производителността

Всеки път, когато даден работник завърши задача, Laravel проверява кеша за сигнали за рестартиране, пауза или продължаване . Това е с незначителни разходи, но съществува. Ако сте изключително фокусирани върху производителността и знаете, че няма да е необходимо да поставяте на пауза или рестартирате работника от команди, можете да деактивирате това запитване, като извикате:

Queue::withoutInterruptionPolling();

Или дори да коригирате статичните свойства на Illuminate\Queue\Worker за да деактивирате определени докосвания ($рестартируем, $pauseableАко обаче направите това и след това се опитате да използвате queue:pause o queue:restartработниците Те няма да разбератТова е дизайнерско решение, което трябва да бъде внимателно обмислено.

Ръчно поставяне на пауза с Supervisor или Docker

В допълнение към собствените команди на Laravel , в производствените среди процесите често се „паузират“ индиректно:

  • Спиране на програмата в Supervisor (supervisorctl stop laravel-worker:*), което убива или спира работниците.
  • използване –спиране-при-празен-стандарт при внедрявания, за да се позволи на работниците да завършат това, което е в опашката, и след това да се затворят.
  • В Docker, оставяйки контейнера да обработва с --stop-when-empty и след това се изключва.

Разликата с queue:pause Чрез пълното спиране на процесите, ще спрете обработката на задачи, докато работниците не се рестартират. вътрешна пауза Можете да запазите процесите в паметта, чакайки командата continueТова е полезно за бързо връщане към предишни внедрявания или кратки периоди на поддръжка.

Транзакции в базата данни и after_commit

Класическа грешка: разпределяне на задачи в рамките на транзакции в базата данни . Ако не внимавате, работникът може да изпълни задачата преди да бъде направено commit-ването, а моделът или данните, които очаквате, може все още да не са в базата данни.

За да избегнете този танц, имате две възможности:

  • Активиране 'after_commit' => true в конфигурацията на връзката с опашката. По този начин всяка задача, изпратена в рамките на транзакция, се отлага вътрешно, докато не бъде потвърдена.
  • Използвайте методи за всяка задача afterCommit() o beforeCommit() при диспечиране, за да се наложи поведението само в конкретни задачи.

Ако транзакцията бъде обърната, задачите, изпратени по време на нея, се отхвърлят, без изобщо да влизат в опашката, което е точно това, което обикновено се желае, за да се поддържа последователност.

Мониторинг, почистване на опашки и тестване

След като опашките са стартирани и работят сериозно, не е достатъчно просто да изхвърлите задачите и да забравите за тях; трябва да наблюдавате и тествате как се държи всичко.

Полезни инструменти и команди:

  • queue:clear за изпразване на определена опашка (SQS, Redis, база данни).
  • queue:monitor да следи броя на задачите в определени опашки и да задейства събитието QueueBusy ако надхвърлят определен праг.
  • Събития за работа като Queue::before, Queue::after, Queue::looping y Queue::failing за закачане на персонализирана логика (логове, показатели, връщане към предишни промени и др.).
  • Фалшификати в тестове използване на Queue::fake() y Bus::fake() за да се провери дали задания, низове или партиди са били изпратени, без реално да бъдат изпълнени.

В тестовете можете да заявите неща като „тази задача е поставена на опашка X пъти“ , „верига с тези задачи е изпратена в този ред“ или „нито една конкретна задача не е поставена на опашка“, което осигурява много сигурност в сложни потоци.

С цялата тази екосистема – драйвери като Redis или SQS, добре проектирани задачи, междинен софтуер за фина настройка, партиди, вериги, конфигурация за повторен опит, управлявани от супервайзор работници и команди като queue:pause y queue:continue— Laravel ви позволява да овладеете фоновата обработка до милиметър, от типичното изпращане на имейли до разпределените архитектури на опашки с превключване на резервни копия, като гарантира, че приложението ви ще продължи да реагира бързо на HTTP нивото, докато отдолу се извършва тежка работа, без да блокира потребителя.

Laravel Framework
Свързана статия:
Мощната рамка на Laravel