Подтвердить что ты не робот

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

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

UPDATE:

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

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

UPDATE:

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

4b9b3361

Ответ 1

Наконец-то я нашел решение (спасибо 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).

Ответ 3

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

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

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

Ответ 4

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

Ответ 5

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

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

Но все ухудшается. Даже если вы создаете дочерний процесс с 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
);

Ответ 6

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

Кэширование

Для кэширования я бы так не сделал. Я бы использовал redis в качестве LRU cache. Это будет очень быстро (тесты), особенно когда вы скомпилируете его с помощью написанной на 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 уже объясняют это:

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

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

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

Ответ 7

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

Ответ 8

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

Возможно, вы можете fork().