PHP

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

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

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

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

Посмотрим реализацию на PHP
set_time_limit(0);
ignore_user_abort(true);
ob_start(); // start buffer
// out page content
echo "This make take some time, please wait";
$length = ob_get_length();
// magic
header('Connection: close');
header("Content-Length: " . $length);
header("Content-Encoding: none");
header("Accept-Ranges: bytes");
ob_end_flush();
ob_flush();
flush();
// background
echo "if you see this, i am not working =(";
//long, long operation
for ($i = 0; $i <= 100000; $i++) {
mail("me@localhost", "spam", $i);
}

Не забывайте про параметр max_execution_time в php.ini, которым ограничено время выполнения вашего скрипта. Content-Encoding установлен в none для того, что бы исключить изменения размера gzip модулями сервера, что приведет к неверной работе. Впрочем это не гарантирует 100% решение проблемы, так что используйте этот трюк с умом.
Теги:
выполнение скрипта
Добавлено: 24 Мая 2018 20:10:13 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...