Это - вопрос о приеме при разработке php+ajax приложения, которое я чувствовал в некоторые долгие запросы, ничто неправильно с ними, но они могли быть сделаны в фоне.
Я знаю, что существует способ просто отправить ответ пользователю при броске реальной обработки в другой процесс должностным лицом (), однако это, dosen't чувствует себя хорошо для меня, это могло бы генерировать использование, и это не практично при создании его совместимый с виртуальными серверами и кросс-платформенный.
PHP предлагает функции ob_*, хотя они помогают на сбрасывании кэша, но пользователь свяжется, пока сценарий не работает.
Я задаюсь вопросом, существует ли альтернатива должностному лицу для хранения сценария, бегущего за передающими данными пользователю и заключительному соединению/потоку с апачем или менее "грязному" способу иметь данные обработки, отправленные в другой сценарий.
Проведя небольшое исследование, я нашел 3 ответа на этот вопрос:
Выполните запрос ajax с низким значением тайм-аута, по достижении тайм-аута JS перейдет к следующему шагу, в то время как php в фоновом режиме с включенным ignore_user_abort
продолжит обработку.
Отделите медленные процессы от сценария, который напрямую отвечает пользователю, выполняя немедленный или частичный ответ (если возможно, в зависимости от случая), сохраняя переменные медленного процесса в _SESSION или базе данных, отправляя их рабочему через cURL с низким значением тайм-аута ИЛИ с задачей cron для вызова рабочих.
Используйте Gearman.
Что я использую на своих сайтах, так это Gearman.
Gearman позволяет запускать рабочие задачи в фоновом режиме через командную строку. Эти рабочие слушают запросы на выполнение определенных задач, а затем обрабатывают их, когда получают запрос.
На стороне веб-приложения я просто делаю $GEARMAN->doBackground("task_name", "task_data");
, после чего задача отправляется рабочему, а выполнение сразу возвращается к скрипту.
Это намного безопаснее, чем выполнение exec
, потому что задача gearman выполняется как PHP-функция.
У меня есть класс PHP, который является демоном POSIX. Я запускаю его, и, по сути, в сценарии есть
while(1)
{
// run task
}
, вы можете помещать вызовы базы данных и все в цикл - он также реагирует на сигналы POSIX - я обычно устанавливаю его в спящий режим на 120 секунд, а затем запускаю снова. Я использую это вместе с небольшой таблицей, которая является моей очередью. Поэтому вместо использования смертоносного exec ()
я могу использовать более безопасный подготовленный оператор для вставки идентификатора в мою таблицу очереди, который фоновый сценарий поймает в следующие 30 секунд.
предостережение - я убиваю демон и перезапускаю его каждые 3 часа, так как иногда он зависает и больше не обрабатывает - но простое уничтожение и запуск каждые 3 часа - хороший компромисс для запуска живых очередей
редактировать Я не хочу публиковать весь сценарий, но могу, если кто-то захочет
В PHP есть функция с именем ignore_user_abort
для этого.
Вы также можете сохранить в базе данных очередь задач для выполнения, а задача cron
периодически проверять наличие новых задач и обрабатывать их по мере их поступления.