Как закрыть соединение и продолжить выполнение скрипта 08.04.2011
Порой перед разработчиком встает задача проделать действительно долгую операцию после отображения страницы, как например рассылка почтовых сообщений или обмен данными с удаленным сервером. Можно положить эту задачу на плечи крона, но если это не удобно/медленно/кошерно, приходится выкручиваться и изобретать странные решения. Одним из таких решений является выполнение долгой операции непосредственно после рендеринга страницы, что может подвесить соединение на пару (десятков, сотен) секунд, или, если поступить добросовестно и оборвать соединение, пройдет незаметно для пользователя. Об этом методе сегодня и поговорим.
Если обратится к спецификации HTTP, можно найти пару замечательных заголовков:
Connection: close - говорит браузеру оборвать соединение при достижении конца файла Content-Length: n - устанавливает длину документа
Посмотрим реализацию на PHP
-
(0);
-
(true);
-
-
(); // start buffer
-
-
// out page content
-
"This make take some time, please wait";
-
-
$length = ();
-
-
// magic
-
('Connection: close');
-
("Content-Length: " . $length);
-
("Content-Encoding: none");
-
("Accept-Ranges: bytes");
-
-
();
-
();
-
();
-
-
// background
-
-
"if you see this, i am not working =(";
-
-
//long, long operation
-
-
for ($i = 0; $i <= 100000; $i++) {
-
("me@localhost", "spam", $i);
-
}
Не забывайте про параметр max_execution_time в php.ini, которым ограничено время выполнения вашего скрипта. Content-Encoding установлен в none для того, что бы исключить изменения размера gzip модулями сервера, что приведет к неверной работе. Впрочем это не гарантирует 100% решение проблемы, так что используйте этот трюк с умом.
Похожие статьи
- Паттерн проектирования Прокси (Proxy) на PHP
- Вышел PHP 5.4a1
- Встроенный Web сервер в PHP
- Вышел NetBeans 7 Beta 2
- Паттерн проектирования Приспособленец (Flyweight) на PHP

мы использовали костыль с маленьким времененм ожидания ответа. просто стучались на нужный адрес с 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);
Делал через register_shutdown_function () (с «промежуточным» 1px изображением или без него)