Может ли такой скрипт "зависнуть"? (long polling)

Zergius2

Новичок
Добрый день,

По мнению техподдержки хостинга, данный скрипт вызывает ошибки сервера (о которых в свою очередь можно почитать здесь
Данный скрипт работает как серверная часть чата реализованного с помощью long polling "технологии". Т.е. клиент с помощью ajax запрашивает этот скрипт, а скрипт отдаёт данные, только если есть новые; если скрипт завершается по истечении $limit секунд, то клиент опять его запрашивает. Скрипт работает нормально. Но, читайте вышеуказанную ссылку...
Есть ли здесь какие либо ошибки могущие подвесить этот скрипт на сервере? Или что иное...

PHP:
session_start();
    $dblocation = "mmm";
    $dbname = "mmm";
    $dbuser = "mmm";
    $dbpasswd = "mmm";
    $dbcnx = @mysql_connect($dblocation,$dbuser,$dbpasswd);
   mysql_query ("SET NAMES 'utf8' COLLATE 'utf8_unicode_ci'");
   mysql_select_db($dbname, $dbcnx);
session_write_close(); //тут берем данные из сессии, и закрываем её
$limit = 25;// number of second the script allowed to run. 
set_time_limit($limit+15);// just to be sure that script will be killed
$time = time();
$last_id = (int)$_POST['id'];
// цикл, проверяющий новые сообщения каждые 5 секунд
while ((time()-$time)<$limit) {
    // checking if something new was added to my test table
    $sql = "SELECT * FROM chat WHERE `msg_id`>".$last_id." ORDER BY `msg_id` DESC LIMIT 50";
    $query = mysql_query($sql);
     if (mysql_num_rows($query)) {   // если есть новые строки в бд  - то обрабатываем и отдаём клиенту
        while ($item=mysql_fetch_array($query)) {
                     // собираем нужные данные из бд
         // и отдаем его клиенту через echo 
        }
        // выбрасываем все данные и выходим, чтобы клиент смог их обработать
        ob_flush();
        flush();
        exit;
    }
    // если данных нет - ждём 5 секунд
    sleep(5);
}
mysql_close();
 

haxyn

Новичок
не понимаю почему ты хочешь крутить скрипт 30 секунд,
а не посылать проверку из javaScript каждые 5 сек
setInterval("getMsg()", 5000);
 

Zergius2

Новичок
не понимаю почему ты хочешь крутить скрипт 30 секунд,
а не посылать проверку из javaScript каждые 5 сек
setInterval("getMsg()", 5000);
Для того что б не грузить соединение постоянными запросами. Такой вариант уже работал раньше. :)
 

DYPA

Настоящая dypa (c)
при минимальной нагрузке long polling на php обречён исчерпанием всей доступной памяти сервера, поэтому я бы бросил эту затею ;)
 

haxyn

Новичок
ну тогда тем более используй мой вариант с JavaScript'ом
нагрузка в 5 человек DDoS'ом не грозит
 

alekciy

Новичок
Да там до 5 пользователей всего, у каждого по два таких скрипта.. Вроде как не густо.
5 * 2 * ~20МБ = 200МБ постоянной ОЗУ только на чатик. Еще и к базе постонно приконекчены. Нужно думать хостинг провайдер негодует сильно.
 

newARTix

Новичок
А почему бы скрипт не убивать штатно? Пусть он сам себя завершает, до достижения тайм-лимита. И ява-скрипт его опять запросит. Не совсем лонг-поллинг конечно, но что-то среднее...
 

alekciy

Новичок
А почему бы скрипт не убивать штатно? Пусть он сам себя завершает, до достижения тайм-лимита. И ява-скрипт его опять запросит. Не совсем лонг-поллинг конечно, но что-то среднее...
А он так и делает ($limit = 25;// number of second the script allowed to run). Хотя конечно более правильно было бы $time_sleep = 5; $time_buf = 3; ... $limit = ini_get('max_execution_time') - $time_sleep - $time_buf .... sleep($time_sleep);
 

newARTix

Новичок
А, точно, туплю. Ну да, лучше сделать какой-то запас по времени, потому что тайм-лимит у фронтенда (апач, энжинкс?) видимо как раз 30 сек. И вполне вероятно что иногда скрипт выполняется 25 сек. + слип(5). Хотя уже сейчас заметно, что вреда от такого лонг-поллинга больше чем пользы. Нетипичное использование фронтенда админам сервера не понравится в любом случае.
 

alekciy

Новичок
потому что тайм-лимит у фронтенда (апач, энжинкс?) видимо как раз 30 сек.
PHP. Ни nginx ни apache подобных лимитов не вносят. Лимиты от веб сервера обычно заключаются в таймаутах на коннект/чтение/запись в соединении. Кстати их автор ни как не учитывает.

И вполне вероятно что иногда скрипт выполняется 25 сек. + слип(5)
Лучше добавить еще некий небольшой запас времени на переходные процессы ($time_buf).
 

newARTix

Новичок
Ни nginx ни apache подобных лимитов не вносят. Лимиты от веб сервера обычно заключаются в таймаутах на коннект/чтение/запись в соединении.
Так вносят или не вносят? :) Лимиты они и в африке лимиты.
 

alekciy

Новичок
Так вносят или не вносят? :) Лимиты они и в африке лимиты.
В данной задача в контексте написания кода не вносят. Потому что программно установить величины этих лимитов невозможно. (Хотя можно узнать эмпирически, но это извращение.) Эти величины можно конечно захардкодить, но вариант плохой ввиду абсолютной неадаптивности.
 

Zergius2

Новичок
max_execution_time установлено 30 секунд;
но, а вот это:
set_time_limit($limit+15)
По идее тут я выставляю новое значение, в данном случае 40 секунд, и скрипт по любому убивается через 40 секунд

5 * 2 * ~20МБ = 200МБ постоянной ОЗУ только на чатик. Еще и к базе постонно приконекчены. Нужно думать хостинг провайдер негодует сильно.
Этот код 20 мб жрёт?
 

alekciy

Новичок
max_execution_time установлено 30 секунд;
но, а вот это:
set_time_limit($limit+15)
По идее тут я выставляю новое значение, в данном случае 40 секунд, и скрипт по любому убивается через 40 секунд
Не сработает, если работа происходит в safe mode. А не вижу, что бы где-то потом была проверка на реальную величину ограничения.

Этот код 20 мб жрёт?
20МБ я обычно беру чисто для прикидки, как среднее по больничке. В зависимости от количества модулей и режима запуска интерпретатор чисто на старте, т.е. не выполнивший еще вообще ни какого кода, потребляет порядка 10МБ для php-fpm и порядка 18МБ apache. К этой памяти прибавляется еще память которая уходит на работу скрипта (тут уж от нуля и до memory_limit), мусор. Получается, что где-то в среднем скрипт у нас гарантированно жрет ~15Мб. Я взял до кучи 20МБ, т.к. наверняка это все крутиться под апачем.

Обычно хостеры за php демоны или долгоживущие скрипты клиента блочат очень быстро, потому как сколько ОЗУ с одного клиента на шаред хостинге в единицу времени это очень много, говорю как бывший работник хостинг-провайдера.
 

alekciy

Новичок
По хорошему чат нужно делать либо на PHP демоне (через тот же libeven), либо вовсе не на PHP, а, к примеру, на Erlang. Но в любом случае демоны в условиях шаред хостинга не живут.
 

флоппик

promotor fidei
Команда форума
Партнер клуба
И еще стоит помнить, что в лимит времени скрипта НЕ считаются запросы к базе, и т.п.
 

флоппик

promotor fidei
Команда форума
Партнер клуба
По хорошему чат нужно делать либо на PHP демоне (через тот же libeven), либо вовсе не на PHP, а, к примеру, на Erlang. Но в любом случае демоны в условиях шаред хостинга не живут.
В условии «два клиента на чат» достаточно просто не делать лонг-поллинг, а делать стандартный хттп запрос, раз в 5 секунд аяксом — там вполне нормально сработает keep-alive для экономии соединений, и это в данном случае будет куда проще и эффективней
 
Сверху