Symfony2 и фоновые процессы

У меня есть класс в моем проекте Symfony 2.3, который выполняет некоторые http-запросы и занимает некоторое время.

Я хотел бы запустить эту задачу как фоновый процесс, чтобы сервер возвращал ответ клиенту, а фоновый процесс продолжал работать.

Вы знаете, как это сделать в Symfony?

Я нашел компонент процесса: http://symfony.com/doc/current/components/process.html, но я не уверен, что смогу запустить оттуда метод класса.


person Milos Cuculovic    schedule 22.11.2013    source источник


Ответы (2)


Простой способ сделать это — отделить тяжелую работу от ответа, используя очередь и команду symfony для обработки очереди.

http://symfony.com/doc/current/components/console/introduction.html

Создайте команду symfony, которая обрабатывает задания, добавленные в очередь, а затем добавьте работу, которую необходимо выполнить, в очередь с вашего контроллера. Очередь, вероятно, будет реализована в виде таблицы заданий базы данных.

Таким образом, вы можете вернуть пользователю ответ об успешном выполнении и регулярно запускать задание cron на сервере для выполнения необходимой вам работы.

person Jon Winstanley    schedule 22.11.2013
comment
Спасибо Джон, я попробую это сегодня. +1 для вас. - person Miloš; 25.11.2013
comment
Использование Cron для рабочих — опасная вещь. Подумайте об этом: вы запускаете воркер каждую минуту с помощью cron, но воркеру требуется больше минуты, чтобы выполнить работу. У вас закончилось множество процессов, конкурирующих за ресурсы, что снижает общую производительность. Сервер может вообще упасть. - person Maksim Kotlyar; 23.06.2017

Это то, что вы можете легко сделать с библиотекой enqueue. Во-первых, вы можете выбирать из множества транспорта. , такие как AMQP, STOMP, Redis, Amazon SQS, файловая система и так далее.

Во-вторых, это очень просто в использовании. Начнем с установки:

Вам необходимо установить библиотеку enqueue/enqueue-bundle и один из транспортов. Предполагая, что вы выбрали библиотеку файловой системы enqueue/fs:

composer require enqueue/enqueue-bundle enqueue/fs 

Теперь давайте посмотрим, как вы можете отправлять сообщения из вашего POST-скрипта:

<?php

use Enqueue\Client\ProducerInterface; 
use Symfony\Component\DependencyInjection\Container;

/** @var Container $container */

/** @var ProducerInterface $producer */ $producer = $container->get('enqueue.client.producer');

$producer->sendCommand('a_background_task', 'task_data');

Для потребления вам необходимо создать службу процессора и пометить ее тегом enqueue.client.processor:

<?php

use Enqueue\Client\CommandSubscriberInterface;
use Enqueue\Psr\PsrContext;
use Enqueue\Psr\PsrMessage;
use Enqueue\Psr\PsrProcessor;

class BackgroundTask implements PsrProcessor, CommandSubscriberInterface
{
    public static function getSubscribedCommand()
    {
        // do job

        return self::ACK;
    }

    public function process(PsrMessage $message, PsrContext $context)
    {
        return 'a_background_task';
    }
} 

И запустите потребителя командой:

./bin/console ставится в очередь: потреблять --setup-broker -vvv

В продукте вам, скорее всего, понадобится более одного потребителя, и если процесс существует, его необходимо перезапустить. Чтобы решить эту проблему, вам нужен своего рода менеджер процессов. Есть несколько вариантов:

http://supervisord.org/ — вам нужен дополнительный сервис. Он должен быть правильно настроен. Такой менеджер процессов на чистом PHP. Основан на компоненте процесса Symfony и чистом PHP-коде. Он может обрабатывать перезагрузку процесса, правильный выход по сигналу sigterm и многое другое. Такой менеджер процессов php\swoole. Для этого требуется расширение PHP swoole, но его производительность потрясающая.

person Maksim Kotlyar    schedule 23.06.2017