Записи с меткой «магия»

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

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

Если обратится к спецификации 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% решение проблемы, так что используйте этот трюк с умом.