php асинхронный вызов и получение ответа от фоновой работы - PullRequest
1 голос
/ 29 января 2010

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

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

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

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

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

Ответы [ 4 ]

3 голосов
/ 29 января 2010

Вы не указываете, на каком языке асинхронный вызов, но я предполагаю, что 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, который считывает файл состояния и возвращает прогресс.

2 голосов
/ 29 января 2010

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

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

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

С

0 голосов
/ 29 января 2010

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

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

Затем клиент может повторно вызывать сервер (например, через другой интерфейс AJAX) для запроса статуса задания, например, "в процессе", "завершено".

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

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

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

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

Все вызовы Ajax по определению асинхронны.

...