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

Тема в разделе "PHP Pro", создана пользователем Горбушка, 31 янв 2016.

XEvil 4.0 Релиз Состоялся!
Статус темы:
Закрыта.
  1. Горбушка

    Горбушка Ищу её...

    Регистр.:
    2 май 2008
    Сообщения:
    3.399
    Симпатии:
    2.363
    Всем привет.

    Имеется скрипт, который до определённого момента готовит пользовательский контент, затем отдаёт пользователю (читать Apache) готовую страницу. Затем происходит расчёт статистики, обновление счётчиков и прочая фигня, которую пользователю дожидаться не обязательно.

    Вопрос - можно ли после отдачи контента Apache'у "сказать" ему, чтобы больше не ждал, но при этом PHP продолжил бы работать и досчитывать показатели в БД?

    Условно:

    PHP:
    <?php

    echo "test";

    // Тут прекращаем ожидать контент от PHP

    while ( $i 1 000 000) {...}

    file_put_content(...);

    ?>
    Вот чтобы пользователь получил свой "test" сразу, а после отработки 1 000 000 раз цикла произошла запись в файл, но пользователь этого уже не ждал...

    Ещё раз для танкистов, после момента отдачи контента больше пользователю ничего отправляться не будет, сессию можно разрывать, процесс Apache останавливать и т.д. Будет идти только запись в БД и файлы, пользователю даже "Ок" отправляться не будет...

    Надеюсь понятно объяснил.
     
  2. KillDead

    KillDead

    Регистр.:
    11 авг 2006
    Сообщения:
    892
    Симпатии:
    564
    Задавался таким же вопросом, но решения не нашёл. Всё сводилось к тому что мы отправляем заголовок что закончили и надеемся что сработает, а это получается далеко не всегда. Ну, есть и немного другие решения - через курл или сокеты но вроде это не по тз, мне не подходило.
     
    Горбушка и latteo нравится это.
  3. dandandan

    dandandan

    Регистр.:
    7 авг 2008
    Сообщения:
    1.033
    Симпатии:
    280
    PHP:
    <?php
    // buffer all upcoming output
    ob_start();
    echo 
    "Here's my awesome web page";
    // get the size of the output
    $size ob_get_length();
    // send headers to tell the browser to close the connection
    header("Content-Length: $size");
    header('Connection: close');
    // flush all output
    ob_end_flush();
    ob_flush();
    flush();
    // close current session
    if (session_id()) session_write_close();
    /******** background process starts here ********/
    Вот решение.
    За отключение браузера от сервера отвечает header('Connection: close');
    Тут несколько примеров... https://www.zulius.com/how-to/close-browser-connection-continue-execution/
    и
    http://stackoverflow.com/questions/138374/close-a-connection-early
     
    Renny и Горбушка нравится это.
  4. pastuhoff

    pastuhoff Постоялец

    Регистр.:
    11 июл 2012
    Сообщения:
    59
    Симпатии:
    8
    Можно подробнее? Не всегда даже в случае использования современных браузеров?
     
  5. Горбушка

    Горбушка Ищу её...

    Регистр.:
    2 май 2008
    Сообщения:
    3.399
    Симпатии:
    2.363
    Тут 2 варианта поведения браузера:
    1) Он отключается и отдаёт заголовок (точно не знаю механизм взаимодействия) о разрыве сессии. Apache принимает его и киляет процесс php, т.к. ответ больше никто не ждёт.
    2) Браузер не разрывает сессию и благополучно ждёт пока её разорвёт Apache... И в итоге человек висит и ждёт не пойми чего, а страница ещё не рендерится даже...

    В общем, на браузеры тут полагаться нельзя. В результате был выбран сценарий следующий:
    1) Мы передаём браузеру заголовок с размером пакета и контент
    2) Разрываем сессию между Apache и nginx, тем самым браузер получает сигнал о прекращении сессии
    3) Сама сессия Apache - PHP продолжает висеть до окончания отработки скрипта, но результат браузеру не передаётся.

    Как-то так...
    Код описан в посте @dandandan + делается настройка сервера чтобы Apache не рвал сессию с PHP.
     
  6. pastuhoff

    pastuhoff Постоялец

    Регистр.:
    11 июл 2012
    Сообщения:
    59
    Симпатии:
    8
    Если php-скрипт запускается через javascript`овый XMLHttpRequest() - убийство этого php-скрипта все-равно возможно (при закрытии браузера или еще при каких-либо обстоятельствах)?
     
    Последнее редактирование: 26 апр 2016
  7. SexKiller

    SexKiller

    Регистр.:
    20 апр 2006
    Сообщения:
    211
    Симпатии:
    45
    +
    Код:
    register_shutdown_function(function(){
        sleep(15);
        file_put_contents('test.txt', 'Проверка записи после завершения скрипта');
    });
    
    Просто находка, спасибо.
     
    KillDead и Горбушка нравится это.
Статус темы:
Закрыта.