Как правильно запускать долгий php-скрипт?

Возникла потребность в том, чтобы запускать php-скрипт (именно php и ничто иное), который заведомо будет долго отрабатывать (до нескольких десятков минут), выводя при этом либо что-то типа прогресс-бара, либо строки с текущим статусом исполнения. Т.е. схема такая: человек кликает по ссылке и видит какой-то прогресс, пока отработка скрипта не завершится.

Как это нынче принято правильно делать? Когда-то для таких вещей запускал через exec, но вдруг что-то новое появилось с тех пор?
  • Вопрос задан
  • 620 просмотров
Решения вопроса 1
Fesor
@Fesor
Full-stack developer (Symfony, Angular)
Вообще более-менее правильный подход:

- пользователь отправляет запрос на сервер
- сервер добавляет задачу в очередь
- обработчик-демон берет задачу и делает ее

По поводу отслеживания прогресса все чуть интереснее. Есть как минимум 4 варианта реализации:
- пулинг - когда периодически мы шлем ajax запрос на сервер и спрашиваем сколько там сделано
- лонг-пулинг - оптимизация первого варианта, при которой запрос не сразу отваливается, а отваливается либо по таймауту (скажем прошло 10 секунд) или же изменилось состояние и нам нужно об этом уведомить пользователя. Как только соединение отвалилось мы обрабатываем что там нам пришло или не пришло и повторяем запрос. Профит - реалтайм нотификация, то есть как-только у нас появилась свежая информация мы можем ее получить.
- Server-sent events, когда запрос отдается нам по кускам с разделителями. Каждый кусок отдается тогда, когда что-то на сервере поменялось. Профит тот же что и в варианте с лонг полингом только не надо разрывать соединение. Но есть куча нюансов (скажем с Apache это не прокатит) и мало кто так делает.
- web sockets - реалтайм, полнодуплексный, удобный вариант, но нужно заводить отдельный демон.

Самый простой вариант - простой пулинг, в вашем случае реалтайм вам не нужен, достаточно раз в 10 секунд спрашивать сервер что там как. В этом случае обработчик очереди (или дочерний процесс или еще кто) может записывать в кэш текущий статус джобы, и вы можете получать ее по идентификатору. в качестве хранилища можно использовать redis или memcache, в этом плане они идеальны.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы