Как заставить скрипт порциями выдавать контент в браузер?

Страшный Злодей

Бывший член клуба (достало хамство).
Как заставить скрипт порциями выдавать контент в браузер?

Есть ли какой-нибудь способ, во время длительной работы скрипта, получать в браузер порции сгенерированного контента?

Причина, по которой мне нужно это делать - на сервере фронтендом к apache, установлен nginx, который, в свою очередь, разрывает соединение, если apache долго не выдаёт ответ. Можно было бы поиграться с директивами типа proxy_read_timeout или запускать скрипт через cron или системный вызов, но в моём случае, перечисленые решения крайне не желательны. Подумалось, что самый удобный вариант это заставить, каким-то образом, apache выдавать ответ порциями, не дожидаясь окончания выполнения скрипта. В этом случае, как мне представляется, nginx не будет считать, что apache "замолчал" и соответственно не станет рвать соединение с сообщением - "504 Gateway Time-out". Уже думал наваять что-то на ajax но перед этим хочется выяснить, возможно все-таки найдутся более простые решения?
 

Страшный Злодей

Бывший член клуба (достало хамство).
В смысле так?
PHP:
for ( условие ) {
ob_start();
echo "то что нужно вывести?";
ob_flush(); 
}
Ещё с самого начала пробовал, то же надеялся, что будет работать. Однако, ни фига - данные выдаются лишь по окончании работы всего скрипта... Ни [m]ob_flush[/m] ни [m]ob_end_flush[/m] не спасли положение..
 

Vin-Diesel

Новичок
хм.. интересно) я похоже раньше с подобной задачей сталкивался, так и не решил её... остановился на ob_flush похоже)
 

Страшный Злодей

Бывший член клуба (достало хамство).
Автор оригинала: phprus
Не ob_flush, а просто [m]flush[/m].
Попробовал в двух вариантах, не помогло :(

первый вариант:
PHP:
for ( условие ) { 
ob_start(); 
echo "то что нужно вывести?"; 
ob_flush();
flush();  
}
второй вариант:
PHP:
for ( условие ) { 
echo "то что нужно вывести?"; 
flush(); 
}
Может, что не так сделал?
 

fixxxer

К.О.
Партнер клуба
это сработает только если не включена никакая буферизация.

как на уровне php (ob_* -- в явном виде, или соответствующие ини-сеттингс -- в неявном), так и на уровне веб сервера (например, если фронтендом стоит nginx то он в любом случае буферизует ответ целиком).

-~{}~ 05.06.10 19:02:

а, ну у тебя собственно nginx и есть.

по хорошему такая задача решается иначе.

при первом запросе запускается параллельный фоновый скрипт, который все делает, и пишет куда-то (скажем в базу) текущее состояние. а клиент опрашивает состояние раз, скажем, с 2 секунды рефрешем или аяксом.
 

Страшный Злодей

Бывший член клуба (достало хамство).
nginx стоит на сервере, я об этом в самом начале написал, но суть все-таки не в этом. я тестировал оба варианта и на своём локальном компе (LAMP), так-же ни один из приведённых выше вариантов не сработал. А вот по поводу ini директив и "на уровне вэбсервера" действительно интересно, если можно что-то из того определить через .htaccess. Существует ли такая возможность?

-~{}~ 05.06.10 19:22:

Автор оригинала: fixxxer
...
по хорошему такая задача решается иначе.

при первом запросе запускается параллельный фоновый скрипт, который все делает, и пишет куда-то (скажем в базу) текущее состояние. а клиент опрашивает состояние раз, скажем, с 2 секунды рефрешем или аяксом.
Про аякс я тоже писал в начале, что без него охота обойтись, ну а за "рефрешить" спасибо, в принципе, если ничего более умного не придумается, то можно и рефрешить, я про этот вариант чего-то и не вспоминал :)
 

dimagolov

Новичок
Страшный Злодей, почитай ман по [m]flush[/m]. там специально разжевано, когда это не сработает, nginx как раз тот случай. поэтому не трать время в пустую и делай ajax-ом
 

Страшный Злодей

Бывший член клуба (достало хамство).
Автор оригинала: dimagolov
Страшный Злодей, почитай ман по [m]flush[/m]. там специально разжевано, когда это не сработает, nginx как раз тот случай. поэтому не трать время в пустую и делай ajax-ом
Да прочитал я ман, там немного о другом говорится, там идёт речь о том, что некоторые сервера, ожидают окночания работы скрипта и только после этого передают результаты в браузер, что [m]flash()[/m] не может заставить такие сервера передавать результаты по мере выталкивания буфера. С этим я как раз илюзий не питаю. Но мне-то достаточно того, чтобы апач передавал результаты для nginx (этот фронтендом стоит), а в браузер пусть они попадают потом, сразу скопом. Лишь бы таймаут не наступал из того, что апач долго не отвечает энгинксу. Т.е. в теории, если апач будет реагировать на [m]flash()[/m] и периодически отдавать данные из буфера в nginx, то проблема решается, так-как "504 Gateway Time-out" означает, что превышено время ожидания между двумя передачами данных от проксированного сервера, к фронтенду (не от фронтенда к браузеру). Это подтвержадет и то, что увеличение значения proxy_read_timeout решает проблему.

ЗЫ: что касается того, что придется юзать аякс или рефреш, то я уже с этим почти смирился :) Но хочется ведь понять, вообще, можно ли каким-нибудь образом черех php или .htaccess устранить ситуацию.. Мне кажется, что должно быть возможно, а вот как, не понятно..
 

dimagolov

Новичок
значения proxy_read_timeout решает проблему.
какую? не возникает ошибка "504 Gateway Time-out"? это лишь означает, что у nginx-а по факту хватает терпения дождаться исполнения php скрипта. клиенту же все попадает одним куском и никакие приседания с flush на это не влияют.

отсюда вывод, что ЗЫ содержит полный бред, а flush вообще не имеет смысла.
 

Страшный Злодей

Бывший член клуба (достало хамство).
Автор оригинала: dimagolov
какую? не возникает ошибка "504 Gateway Time-out"? это лишь означает, что у nginx-а по факту хватает терпения дождаться исполнения php скрипта. клиенту же все попадает одним куском и никакие приседания с flush на это не влияют.

отсюда вывод, что ЗЫ содержит полный бред, а flush вообще не имеет смысла.
Упс.. :-(

Чего так категорично?

Вопрос конечно, по ходу данного обсуждения, немного трансформировался, если в начале требовалось порционная выдача браузером, то теперь я согласен на то, чтобы браузер выводил все сразу, лишь бы nginx не разрывал соединение... Поэтому если "у nginx-а по факту хватает терпения дождаться исполнения php скрипта" то, это то-что нужно, вот только реализовано это через корневые директивы сервера, а хотелось бы найти способ сделать это средствами php или .htaccess. Почему это нужно назвать бредом?
 

Fortop

Новичок
Менять надо настройки буферизации в апаче и php.

Чтобы никто из них ничего не зажимал. Тогда flush() будет порциями выталкивать ответ nginx'у

Но если
proxy_read_timeout решает проблему
то мне кажется проще решить именно таким способом.
 

fixxxer

К.О.
Партнер клуба
Автор оригинала: Fortop
Менять надо настройки буферизации в апаче и php.

Чтобы никто из них ничего не зажимал. Тогда flush() будет порциями выталкивать ответ nginx'у

Но если
то мне кажется проще решить именно таким способом.
nginx ничего не отдаст пока не получит целиком
так что смысла нет
 

Fortop

Новичок
fixxxer
ну, проблема была ведь именно в 504 Gateway Time-out
собственно для ее решения абсолютно неважно отдаст ли nginx все одним куском или частями.

Или я что-то пропустил?
 

Страшный Злодей

Бывший член клуба (достало хамство).
Автор оригинала: Fortop
fixxxer
Или я что-то пропустил?
Да тут многие чего-то пропустили.. :) Так fixxxer пропустил, что главная проблема это "504 Gateway Time-out", dimagolov пропустил, что задача по ходу обсуждения трансформировалась, а ты пропустил, что изменять proxy_read_timeout крайне не желательно :)

Ребята, я правда искренне благодарен Вам всем за Вашу помощь и участие в решении моей проблемы - спасибо! Но все-таки, ради будущих поколений, которые будут читать архив форума, а ровным счётом и ради нас самих, призываю - прежде чем отвечать, читайте темы внимательнее! :)

ЗЫ: конкретную задачу, ради решения которой поднималась тема, решена - плюнул и сварганил ajax модуль. вопросы относительно существования других решений остались, но это видимо никому кроме меня не интересно, так-что пусть модераторы поступят с темой на своё усмотрение.
 

Mols

Новичок
Страшный Злодей
Ну почему не интересно. Теоретически интересно. Вот только есть ли увереность, что nginx выдает ошибку "504 Gateway Time-out" только в том случае если он не_начал_получать ответ? Я почти уверен, что ему пофиг начал он или нет,(а значит и flush(); не поможет). Ковырять лень естессно.
З.Ы.
Ну а путаницу Вы сами внесли. Тема говорит "порциями в браузер" а по сути вопрос другой.
 

fixxxer

К.О.
Партнер клуба
nginx отдает 504 если он не дождался ответа целиком.

nginx работает с бэкендом по протоколу http/1.0, соответственно, пока не наброано тело длиной в content-length или, при отсутствии такового, пока бэкендом не закрыто соединение, идет ожидание. соответственно 504 будет даже если не дождались одного байта из 100500.

мне просто казалось что это все знают :D
 

Fortop

Новичок
мне просто казалось что это все знают
Я, например, с nginx не работал :) поэтому и не знаю.
Получается что ни таймауты ни буферизация тут вовсе не причем? Нужно просто отдать корректный контент с HTTP 1.0
 

Страшный Злодей

Бывший член клуба (достало хамство).
А я хоть и юзаю энгинкс, но в протоколы его не влазил.. Теперь внимательнее изучу этот момент.

А товарищу fixxxer незачет! Столь важную вещь, до последнего скрывал.., с каких щей тут все такие умные должны быть? ;)
 
Сверху