Как закрыть соединение и продолжить выполнение скрипта 08.04.2011

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

Если обратится к спецификации HTTP, можно найти пару замечательных заголовков:

Connection: close - говорит браузеру оборвать соединение при достижении конца файла
Content-Length: n - устанавливает длину документа

Посмотрим реализацию на PHP

  1.  
  2. ob_start(); // start buffer
  3.  
  4. // out page content
  5. echo "This make take some time, please wait";
  6.  
  7. $lengthob_get_length();
  8.  
  9. // magic
  10. header('Connection: close');
  11. header("Content-Length: "$length);
  12. header("Content-Encoding: none");
  13. header("Accept-Ranges: bytes");
  14.  
  15.  
  16. // background
  17.  
  18. echo "if you see this, i am not working =(";
  19.  
  20. //long, long operation
  21.  
  22. for ($i = 0; $i <= 100000; $i++) {
  23.     mail("me@localhost", "spam"$i);
  24. }

Не забывайте про параметр max_execution_time в php.ini, которым ограничено время выполнения вашего скрипта.  Content-Encoding установлен в none для того, что бы исключить изменения размера gzip модулями сервера, что приведет к неверной работе. Впрочем это не гарантирует 100% решение проблемы, так что используйте этот трюк с умом.


,


Похожие статьи


  1. AmdY:

    мы использовали костыль с маленьким времененм ожидания ответа. просто стучались на нужный адрес с CURLOPT_TIMEOUT=1

    $ch = curl_init ();

    curl_setopt ($ch, CURLOPT_URL,'http://'.$_SERVER['HTTP_HOST'].'/taskUrl/');

    curl_setopt ($ch, CURLOPT_TIMEOUT, 1);

    curl_exec ($ch);

  2. Делал через register_shutdown_function () (с «промежуточным» 1px изображением или без него)

    www.levik.info/php-cron-without-cron.htm

Добавить комментарий