php асинхронный вызов и получение ответа от фонового задания

Я проделал поиск по этой теме в Google и не смог найти ответ на мой вопрос.

Я хочу достичь следующего:

  1. клиент выполняет асинхронный вызов функции на сервере
  2. сервер выполняет эту функцию в фоновом режиме (поскольку эта функция занимает много времени), и клиент не висит в это время
  3. клиент постоянно делает вызов на сервер, запрашивая статус фонового задания

Не могли бы вы дать мне несколько советов по решению моей проблемы?

Большое спасибо! ^ – ^

    Вы не указываете, на каком языке находится асинхронный вызов, но я предполагаю PHP на обоих концах. Я думаю, самый элегантный способ:

    • Загрузка HTML-страницы определяет случайный ключ для операции (например, с помощью rand() или уже доступного идентификатора сеанса [будьте осторожны, хотя один и тот же пользователь может запускать две операции))

    • HTML-страница делает вызов Ajax сценарию PHP для start_process.php

    • start_process.php выполняет exec /path/to/scriptname.php для запуска процесса; см. примечания пользователя, внесенные в exec() в рекомендации о том, как запустить процесс в фоновом режиме. Какой из них подходит вам, зависит в основном от вашей ОС.

    • long_process.php часто записывает свой статус в файл состояния, названный в честь случайного ключа, сгенерированного вашей страницей Ajax

    • HTML-страница часто вызывает вызовы show_status.php который считывает файл состояния и возвращает прогресс.

    Имейте google для длительных процессов php (будьте предупреждены о том, что в этой теме есть много плохих советов – в том числе записка, на которую ссылается Pekka – это будет работать на Microsoft, но на что-нибудь еще не будет непредсказуемым).

    Вы могли бы разработать службу, которая отвечает запросам через сокет (ваш клиент будет использовать fsockopen для подключения) – некоторые простые способы достижения этой цели состоят в использовании сервера Socket Aleksey Zapparov ( http://www.phpclasses.org/browse/package /5758.html ), который обрабатывает запросы, поступающие через сокет, но поскольку это работает как один поток, это может быть не очень подходящим для чего-то, что требует много обработки. Альтернативно, если вы используете систему, отличную от Microsoft, тогда yo может повесить ваш скрипт с [x] inetd, однако вам нужно будет сделать некоторые умные вещи, чтобы предотвратить его завершение, когда клиент отключается.

    Чтобы сохранить работу после того, как клиент отключится, код PHP должен запускаться из автономного исполняемого файла PHP (а не через веб-сервер). Создайте процесс в новой группе процессов (см. Posix_setsid () и pcntl_fork ()). Чтобы позволить клиенту вернуться и проверить прогресс, самым простым способом добиться этого является настройка сервера для выписывания его статуса в том месте, где клиент может читать.

    C.

    1. Ajax call run method longRunningMethod () и возвращает идентификатор (например, идентификатор)
    2. Сервер запускает этот метод и устанавливает ключ, например, sharedmem
    3. Клиент вызывает checkTask (id)
    4. сервер ищет ключ в sharedmem и проверяет состояние готовности [повтор 3 и 4 до 5 завершен]
    5. Команда longRunningMethod завершена и устанавливает состояние для завершения в sharedmem.

    Все вызовы Ajax для каждого асинхронного определения.

    Вы можете (хотя и не строго необходимый) использовать AJAX для создания экземпляра вызова, и сценарий затем может создать ссылку на статус фонового задания в общей памяти (или даже временную запись в таблице SQL или даже временную файл), в виде уникального идентификатора задания.

    Затем скрипт может начать фоновый процесс и сразу же вернуть идентификатор задания клиенту.

    Затем клиент мог вызвать сервер несколько раз (через другой интерфейс AJAX, например), чтобы запросить статус задания, например, «in progress», «complete».

    Если фоновый процесс, который должен быть выполнен, сам написан на PHP (например, скрипт PHP командной строки), вы можете передать ему идентификатор задания, и он может предоставить осмысленные обновления выполнения для клиента (путем записи в ту же область общей памяти, или таблицы базы данных).

    Если выполняемый процесс сам не написан на PHP, я предлагаю обернуть его в PHP-скрипт командной строки, чтобы он мог отслеживать, когда выполняемый процесс завершен (и проверить вывод, чтобы увидеть, был ли он успешным) и обновить статус для этой задачи.

    Примечание. Использование общей памяти для этого – лучшая практика, но может быть недоступно, если вы используете, например, общий хостинг. Не забывайте, что вы хотите иметь средства для очистки старых записей состояния, поэтому я бы сохранил значения «start_on» / «completed_on» timestamps для каждого из них и удалил записи для устаревших данных (например, с меткой времени завершения более X минут – и, в идеале, это также проверяет работу, которая началась некоторое время назад, но никогда не была отмечена как завершена и вызывает предупреждение о них).