2010-07-17 2 views
4

Кто-нибудь знает, как закрыть соединение (кроме flush()?), Но продолжайте выполнение некоторого кода впоследствии.Закройте соединение с PHP, но продолжайте выполнение скрипта

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

+2

, что соединение – Starx

+1

Зачем вам тоже? Для запуска обычного сценария PHP занимает всего миллисекунды. Все, что занимает больше времени, не должно быть доступно широкой публике. – animuson

+0

animuson, хотя я согласен с вашим заявлением в целом, мы не знаем, доступно ли это приложение/веб-сайт для широкой публики. Это может быть приложение, работающее где-то внутри. Поэтому я не вижу релевантности вашего комментария ... – kander

ответ

9

Возможно, вам стоит взглянуть на pcntl_fork() - он позволяет вам развернуть свой текущий скрипт и запустить его в отдельном потоке.

Я использовал его в проекте, в котором пользователь загрузил файл, а затем сценарий выполнил различные операции над ним, включая связь с сторонним сервером, что может занять много времени. После начальной загрузки сценарий разворачивал и отображал следующую страницу для пользователя, а родитель убивал себя. Затем ребенок продолжил выполнение и был запрошен возвращенной страницей для ее статуса с использованием AJAX. это сделало приложение гораздо более отзывчивым, и пользователь получил обратную связь относительно статуса во время его выполнения.

Эта ссылка имеет больше о том, как использовать его:

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


mvds напоминает следующее (который может применяться в конкретной конфигурации сервера): Не fork весь сетевой сервер Apache, но запускать отдельный процесс вместо этого. Пусть этот процесс развивает ребенка, который живет. Найдите proc_open, чтобы получить полное fd-взаимодействие между вашим скриптом php и процессом.

+0

Обратите внимание, что вы можете использовать только pcntl_fork() (в этом контексте) с настраиваемым http-сервером, написанным на php, поэтому обычно этот ответ можно использовать только около 0.0001% времени;) – nathan

+0

Я использовал Apache. – Jhong

+0

Тогда я думаю, что вы все-таки разыграете весь демон apache. Это не красивое зрелище и, вероятно, не предполагаемое использование модуля apache ... – mvds

5

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

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

Ключ здесь, на который указывает ответ Jhong и обратно предложенный комментарием animusen, заключается в том, что вся суть того, что мы делаем с HTTP в качестве веб-разработчиков, - это как можно быстрее ответить на запрос/конец - вот и все, поэтому, если вы делаете что-нибудь еще, тогда это указывает на какое-то дизайнерское решение, которое, возможно, было бы немного лучше :)

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

Точное решение зависит от того, что вы делаете, и ответа на другой (набор) вопросов; но для этого он сводится к: нет, вы не можете закрыть соединение, и вы бы посоветовали вам пересмотреть долговременный процесс из этого сценария/страницы.

3

Не используйте fork весь веб-сервер apache, но вместо этого запустите отдельный процесс. Пусть этот процесс развивает ребенка, который живет. Найдите proc_open, чтобы получить полное fd-взаимодействие между вашим скриптом php и процессом.

+0

Это, скорее всего, дополнение к существующему ответу, особенно более длинный страх, который у вас есть, что pcntl_fork сделает что-то плохое/ресурсоемкое в очень особенном Apache + PHP внутри использования модуля Apache SAPI. Это должен быть комментарий к существующему ответу или дополнительному правлению для того, о чем нужно думать при использовании этого ответа, а не о дополнительном ответе, потому что это не совсем понятно для того, что стоит. Я объединил его и попрошу удалить его. - Также, поскольку я больше об этом думаю, должна быть какая-то ссылка, которая объясняет это лучше, например, ссылку, возможно, на 'fork' в PHP. – hakre

+0

@hakre Я не согласен с тобой. Вопрос заключается в следующем: «Как запустить код после запуска PHP-скрипта», и ответ заключается в том, чтобы «запустить отдельный процесс вместо этого. Позвольте этому процессу отменить дочерний процесс, который живет. Посмотрите, чтобы proc_open получил полное fd-взаимодействие между вашим php-скриптом и процесс ». – mvds

+0

@hakre, и если вы не согласны, просто downvote, так работает этот сайт. – mvds

4

Посмотрите на PHP's ignore_user_abort-setting. Вы можете установить его, используя ignore_user_abort() function.

example of (optional) use был дан (и было сообщено работает на ОП) в следующем дубликата вопрос:

Это в основном дает ссылки на пользовательских заметок в PHP руководстве , Центральная одна

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

+0

Настоящий * лучший ответ. Он утверждает, что клиенту не нужно знать результат процесса, поэтому ему не нужно использовать forking, очереди или любой из этих вещей. – pjbeardsley

+0

@pjbeardsley: На самом деле это не лучший ответ, потому что он приходит с некоторыми проблемами незаметно: во-первых, '' ingnore_user_abort' * является необязательным в соответствии с связанными источниками, но названными первыми и необходимыми. Во-вторых, ответ, представленный здесь, был дан ранее и не был связан. Также отсутствовал исходный код (это также было проблемой для связанного дубликата, но теперь исправлено). Тем не менее, связанные примеры, представленные, делают то, что вы говорите для некоторых конфигураций webserver/php, достаточно хорошо и являются своего рода * общим * для этого. Так что это не совсем плохой ответ. – hakre

2

Мы решили эту проблему, вставив работу, которая должна быть выполнена в очередь заданий, а затем попросите cron-скрипт регулярно выполнять backend-задания. Вероятно, это не совсем то, что вам нужно, но оно очень хорошо работает для процессов с интенсивным использованием данных.

(вы также можете использовать очереди заданий Zend Server, в если у вас есть пачка денег и хотят проверенный и отработанный раствор)

Смежные вопросы