Длинный опрос PHP работает бесконечно

Я создаю веб-сайт с функцией чата, и мне нужно отслеживать пользователей онлайн и офлайн. Для отслеживания онлайн-пользователей я использую эту таблицу

идентификатор_пользователя | отметка времени

Я обновляю отметку времени каждые 20 секунд для всех онлайн-пользователей. Поэтому я могу узнать, кто из них не в сети, просто сравнив текущую отметку времени с отметкой времени в таблице.

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

<?php
set_time_limit(0);

while(1){
  updateUserTimestamp();
  sleep(20);
}
?>

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

Пожалуйста помоги.


person ajaybc    schedule 01.09.2011    source источник
comment
Вау.. ты не хочешь этого делать. Это поддерживает бесконечное выполнение PHP-процесса на вашем сервере. Разве вы не можете сделать это в каком-то глобальном классе/скрипте вашего приложения?   -  person Rijk    schedule 01.09.2011


Ответы (5)


Попробуйте следующее решение (см. документацию по функции connection_aborted()):

<?php
set_time_limit(0);

while(!connection_aborted()){
    updateUserTimestamp();
    sleep(20);
}

В качестве альтернативы вы можете настроить сценарий на прерывание, когда клиент закрывает соединение. Подробнее см. документацию по ignore_user_abort.

Но если у вас может быть много одновременных запросов, возможно, будет хорошей идеей либо

  1. отказаться от использования длительного опроса в пользу частых запросов AJAX или
  2. использовать решения на стороне сервера, подобные Node.js, которые не используют много ресурсов для дополнительных запросов.
person Tadeck    schedule 01.09.2011
comment
Я использую общий веб-хостинг и не могу установить новое серверное программное обеспечение :( Спасибо, я попробую приведенный выше код и опубликую результаты. - person ajaybc; 01.09.2011
comment
Голосую за это, так как это лучший ответ из всех, но ОП обязательно должен принять совет Тадека близко к сердцу. Подобный цикл while () на стороне сервера никогда не бывает хорошей идеей. - person broofa; 02.09.2011

Но проблема в том, что даже после того, как пользователь закрывает браузер, он продолжает работать как призрачный процесс и продолжает обновлять метку времени и занимать ресурсы. Я хочу, чтобы он останавливался, когда клиент закрывает браузер.

Именно поэтому вы не хотите этого делать. Вам нужно удалить этот сценарий и переместить updateUserTimestamp() в какой-нибудь глобальный сценарий, который часто вызывается, в идеале сценарий, в котором изменяется статус пользователя (потому что, если статус пользователя не меняется, его также не нужно обновлять).

person Rijk    schedule 01.09.2011

На каком сервере вы это запускаете? Этого не должно происходить, потому что, когда пользователь закрывает браузер, он также должен убить запрос AJAX и закрыть TCP-соединение, а сервер должен принять это к сведению и убить запущенный процесс/поток PHP.

Попробуйте добавить событие window.onunload на стороне клиента, которое убивает все активные запросы AJAX, и посмотрите, имеет ли это значение.

person DaveRandom    schedule 01.09.2011

Ваш код продолжает обновлять статус без каких-либо доказательств того, что пользователь все еще подключен или активен. Если пользователь просто выключит свой компьютер, он будет работать вечно, даже если сможет обнаружить закрытие соединения. (Выключенный компьютер не может закрыть соединение, не так ли?)

Вы должны заставить пользователя делать что-то каждые 20 секунд, что запускает обновление. Вы можете решить, что это за что-то, и это может быть что угодно. Но должно быть что-то, что пользователь делает, чтобы вы считали его активным. Вы не можете просто считать его активным навсегда, что и делает ваш код.

person David Schwartz    schedule 01.09.2011

Чтобы никогда не завершать процессы, заставьте скрипт завершаться после 20-секундного ожидания и заставляйте клиента открывать новое соединение. Вы сохраните преимущества длинного опроса, но больше не будете иметь призрачных процессов.

person nikc.org    schedule 01.09.2011