nepster-web
@nepster-web

Почему не работает flush()?

Использую SEE и наткнулся на такой косяк:

На локальном сервере все работает:
public function actionUpdateProposals()
    {
        // id игры 
        $game_id = (isset($_GET['id']) && is_numeric($_GET['id'])) ? (int)$_GET['id'] : 0;
        
        set_time_limit(120);

        header('Content-type: text/html; charset=utf-8');
        header('Content-Type: text/event-stream');
        header('Cache-Control: no-cache');
        header("Access-Control-Allow-Origin: *");
        
        $start = time();
        
        $lastEventId = floatval(isset($_SERVER["HTTP_LAST_EVENT_ID"]) ? $_SERVER["HTTP_LAST_EVENT_ID"] : 0);
        if ($lastEventId == 0) 
        {
            $lastEventId = (isset($_GET["key"])) ? (string)$_GET["key"] : 0;
        }
        
  
        while(true) 
        {
            //if ((time() - $start) > 10) {break;}
        
            //echo ":" . str_repeat(" ", 2048) . "\n"; // 2 kB padding for IE
            echo "retry: 2000\n";
            echo "id: {$lastEventId}" . PHP_EOL;
            echo "data: " . GameOperations::load()->getJsonProposalsData($game_id) . PHP_EOL;
            echo PHP_EOL;
            
            ob_flush();
            flush();
        }
        
    }


Что должно быть:
Соединяемся держим соединение 2 минуты, в это время каждые 5 секунд отдаем данные.
На локалке все хорошо (апатч)

Переносим на сервер (нгинкс) и выхватываем:
Ждет 2 минуты, конектиться отдает данные теряет соединение. Ждет 2 минуты и так далее...

Прочитал про всякие настройки типа:
output_buffering = Off
zlib.output_compression = Off


Поставил, теперь выглядит вот так:
Соединение
Обновление данных
Потеря соединения
Соединение
Обновление данных
Потеря соединения
Соединение
Обновление данных
Потеря соединения

И так бомбит постоянно.

на нгинксе добавил:
gzip off;
	proxy_buffering off;


Всеравно не спасло.

Подскажите пожалуйста в чем проблема ?
  • Вопрос задан
  • 9352 просмотра
Решения вопроса 4
nazarpc
@nazarpc
Open Source enthusiast
В PHP есть какой-то буфер, пока он не наполнится - flush() не отправит данные клиенту.
Для его заполнения я использовал пробелы, можете посмотреть код тут:
https://github.com/nazar-pc/CSTester/blob/master/s...
Это заставляет возвращать данные клиенту как только это вам необходимо, не дожидаясь заполнения буфера.
Ответ написан
@art_gur
Здравствуйте!
Я думаю, что обрыв соединения идёт из-за следующей причины.
У php есть такая настройка, как Время выполнения скрипта, по умолчанию это время равно 30 секундам. Попробуйте изменить значение этой переменной на нужное Вам время, к примеру на 5 минут (300 cекунд)
Ответ написан
egor_nullptr
@egor_nullptr
Попробуйте ob_implicit_flush(true) в начале функции вместо flush() и ob_flush() в цикле. Также попробуйте fastcgi_buffering = off в настройках nginx (если у вас nginx+php-fpm).
Ответ написан
Комментировать
nepster-web
@nepster-web Автор вопроса
Ситуация стала интереснее. Оказывается там была ошибка (ее Yii роутил)

ob_flush(): failed to flush buffer. No buffer to flush.

если прикрыть собакой или в самом начале скрипта поставить ob_start();

Реакция такая:
Ждем секунд 12 выбрасываем сразу 7 запросов
Ждем секунд 12 выбрасываем сразу 7 запросов
Ждем секунд 12 выбрасываем сразу 7 запросов
Ждем секунд 12 выбрасываем сразу 7 запросов
Ждем секунд 12 выбрасываем сразу 7 запросов

Уже ближе к теме, но откуда такие задержки и почему сразу данные пачкой бросает а не раз в 2 секунды ?
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
SergeAx
@SergeAx
Серийный технический ко-фаундер
Выдавай после каждого запроса килобайт сколько-нибудь пробелов.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы