Продолжить обработку после закрытия соединения

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

ОБНОВИТЬ:

PLUS имеет самый близкий ответ на то, что я искал. Чтобы уточнить пару людей, я ищу что-то, что позволяет выполнить следующие шаги:

  1. Страница пользовательских запросов
  2. Соединение открывается серверу
  3. PHP проверяет, истек ли кеш, если он еще свежий, обслуживает кеш и закрывает соединение (КОНЕЦ ЗДЕСЬ). Если истек, продолжайте до 4.
  4. Подавать истекший кеш
  5. Закрыть соединение, так что браузер знает, что он не ждет больше данных.
  6. PHP регенерирует свежие данные и кэширует их.
  7. PHP отключается.

ОБНОВИТЬ:

Это важно, это должно быть чисто PHP-решение. Установка другого программного обеспечения не является вариантом.

Related of "Продолжить обработку после закрытия соединения"

Если вы работаете под управлением fastcgi, вы можете использовать очень стильный:

fastcgi_finish_request ();

http://php.net/manual/en/function.fastcgi-finish-request.php

Более подробная информация доступна в двух экземплярах .

Я, наконец, нашел решение (спасибо Google, мне просто пришлось пытаться использовать разные комбинации поисковых запросов). Благодаря комментарию от arr1 на этой странице (это примерно две трети пути вниз по странице).

<?php ob_end_clean(); header("Connection: close"); ignore_user_abort(); // optional ob_start(); echo ('Text the user will see'); $size = ob_get_length(); header("Content-Length: $size"); ob_end_flush(); // Strange behaviour, will not work flush(); // Unless both are called ! // Do processing here sleep(30); echo('Text user will never see'); ?> 

Мне еще предстоит проверить это, но вкратце. Вы отправляете два заголовка, один из которых сообщает браузеру, сколько данных ожидает, чтобы сообщить браузеру о закрытии соединения (которое он будет делать только после получения ожидаемого количества контента). Я еще не тестировал это, и я не знаю, что нужен sleep(30) .

Вы можете сделать это, установив ограничение по времени на неограниченное и игнорируя соединение

 <?php ignore_user_abort(true); set_time_limit(0); 

см. также: http://www.php.net/manual/en/features.connection-handling.php

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

Насколько я знаю, если вы не используете FastCGI, вы не можете удалить соединение и продолжить выполнение (если только вы не получили ответ Endophage на работу, который я не смог). Так что вы можете:

  1. Используйте cron или что-то в этом роде для планирования таких задач
  2. Используйте дочерний процесс для завершения работы

Но становится все хуже. Даже если вы создаете дочерний процесс с proc_open() , PHP будет ждать завершения до закрытия соединения даже после вызова exit() , die() , some_undefined_function_causing_fatal_error() . Единственным обходным решением, которое я нашел, является создание дочернего процесса, который сам порождает дочерний процесс, например:

 function doInBackground ($_variables, $_code) { proc_open ( 'php -r ' . escapeshellarg ("if (pcntl_fork() === 0) { extract (unserialize (\$argv [1])); $_code }") . ' ' . escapeshellarg (serialize ($_variables)), array(), $pipes ); } $message = 'Hello world!'; $filename = tempnam (sys_get_temp_dir(), 'php_test_workaround'); $delay = 10; doInBackground (compact ('message', 'filename', 'delay'), <<< 'THE_NOWDOC_STRING' // Your actual code goes here: sleep ($delay); file_put_contents ($filename, $message); THE_NOWDOC_STRING ); 

Может компилировать и запускать программы из PHP-CLI (не на общедоступном хостинге> VPS)

Кэширование

Для кэширования я бы так не сделал. Я бы использовал redis как свой кеш LRU . Это будет очень быстро (тесты), особенно когда вы скомпилируете его с клиентской библиотекой, написанной на C.

Автономная обработка

Когда вы устанавливаете очередь сообщений beanstalkd, вы также можете откладывать puts. Но я бы использовал redis brpop / rpush для выполнения другой очереди сообщений, потому что redis будет быстрее, особенно если вы используете PHP-клиентскую библиотеку (в C-пространстве пользователя).

Невозможно скомпилировать или запустить программы из PHP-CLI (на общем хостинге)

set_time_limit

в большинстве случаев этот параметр set_time_limit недоступен (из-за директивы safe-mode или max_execution_time ), чтобы установить 0, по крайней мере, когда на общем хостинге. Также общий хостинг действительно провайдеры не любят, чтобы пользователи долго удерживали процессы PHP. В большинстве случаев ограничение по умолчанию равно 30.

Cron

Используйте cron для записи данных на диск с помощью Cache_lite . Некоторые темы stackoverflow уже объясняют это:

  • crontab с wget – почему он работает дважды?
  • Команды Bash не выполняются при выполнении задания cron – PHP
  • Как я могу отлаживать скрипт PHP CRON, который не работает?

Также довольно легко, но все же взломанный. Я думаю, что вы должны обновить (> VPS), когда вам нужно сделать такой взлом.

Асинхронный запрос

В качестве последнего средства вы можете сделать асинхронные запросы кэширования данных, например, с помощью Cache_lite. Имейте в виду, что для общего хостинга вам не нравится поддерживать много длительных PHP-процессов. Я бы использовал только один фоновый процесс, который вызывает другой, когда он достигает директивы max-execution-time . Я хотел бы отметить время, когда начинается скрипт, и между несколькими вызовами кеша я буду измерять потраченное время, и когда он приблизится ко времени, когда я сделаю еще один асинхронный запрос. Я бы использовал блокировку, чтобы убедиться, что работает только один процесс. Таким образом, я не буду мочиться у провайдера, и это можно сделать. С другой стороны, я не думаю, что я напишу об этом, потому что это хакка, если вы спросите меня. Когда я доберусь до этой шкалы, я перейду на VPS.

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

Нет. Что касается веб-сервера, запрос от браузера обрабатывается движком PHP, и все. Запрос длится до тех пор, как PHP.

Возможно, вы можете использовать fork() .