Отслеживание зарегистрированных пользователей в PHP - PullRequest
6 голосов
/ 24 августа 2011

Я пытаюсь написать простое приложение для чата с PHP и AJAX.

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

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

  • сеанс на стороне сервера истекает после неактивности.
  • cookie на стороне клиента уничтожается при закрытии браузера. Похоже, плохая идея использовать какой-то AJAX, запускаемый onclose (что, если в браузере происходит сбой или что-то в этом роде?).

Кажется, простейшим решением является сохранение отметки времени последней активности. Я вижу некоторые проблемы с этим, хотя:

  • AFAIK истечение срока действия на стороне сервера основано на случайности, поэтому оно не будет точным (и если я получу неправильное время истечения 3 минуты, это будет 3 минуты, когда какой-то парень может разговаривать с офлайн-пользователем, задаваясь вопросом, почему никто не отвечает )
  • Мне пришлось бы постоянно запрашивать базу данных, чтобы проверить время последней активности каждого зарегистрированного пользователя по сравнению с текущим временем. Я не вижу, когда и где я бы сделал это эффективно. Кажется глупым делать это каждый раз, когда нужен список онлайн-пользователей.

Любая помощь приветствуется. Я сам кодирую это, потому что мне неизвестны какие-либо фреймворки веб-чатов, которые могут интегрироваться с моей существующей базой данных пользователей, исправьте меня, если я ошибаюсь.

Ответы [ 7 ]

1 голос
/ 24 августа 2011

Вы можете инвертировать свой шаблон, заменив поведение Ajax pull на систему push-уведомлений.

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

Это немного сложнее, чем с помощью ajax pull, но однаждыреализована основная структура, вы можете легко добавить функциональность, и производительность будет намного лучше.

Некоторые полезные ссылки, которые я нашел:

Это эпизод Railscast, который касается чата javascript, реализация в рельсах, но даже если вы не понимаете,рельсы вы должны быть в состоянии следовать за ним, чтобы получить основные понятия: http://railscasts.com/episodes/260-messaging-with-faye

1 голос
/ 24 августа 2011

Я не думаю, что вы сможете многое сделать, чтобы уменьшить количество постоянных запросов, чтобы определить, вышли ли пользователи из системы, закрыв браузер, из-за проблем с интернет-соединением и т. Д., Но, возможно, каждый клиент может сделать AJAX-запрос к серверу каждые 5 секунд, чтобы обновить время последней активности, и чтобы ваше приложение на сервере считало пользователя «отключенным», если он пропустил 3-4 последовательных запроса (т. е. их последнее время активности> 20 секунд). ).

На стороне клиента вы можете проверять время последней активности каждый раз, когда ваш клиент отправляет сообщение другому пользователю, и отвечать, что он вышел из системы, если это произошло. Если они попытались открыть чат с другим пользователем, вы также можете сделать немедленный звонок, чтобы проверить его статус. Затем вы можете проверять статус всех пользователей в списке пользователей каждые 30 секунд. Таким образом, ваш клиент получает довольно быструю обратную связь, если человек, с которым он общается, неожиданно отключается.

0 голосов
/ 12 марта 2012

Я опоздал на эту вечеринку, но позвольте мне дать два моих цента.

В этом конкретном сценарии нет необходимости использовать систему push для плохих уведомлений. Также нет необходимости в cron. Позвольте мне объяснить:

Допустим, A, B и C находятся в чате, а браузер B вылетает, поэтому его сеанс истекает. Прямо сейчас сервер думает, что B все еще там, но ее нет. Как вы обновляете A & C? Когда A & C просит об обновлении. Проверьте последнюю временную метку keepalive и выясните, что срок их сеанса истек.

Если все А, В и С потерпят крах, то этого никогда не произойдет, я слышу, вы спрашиваете. Какая разница? Сейчас никто не видит нашей ошибки! Единственным недостатком является поддержание их чата в живых, что требует некоторого пространства базы данных Это можно исправить при создании другого сеанса чата.

Финальная суть:

  1. Сохранять временные метки в последний раз, когда было предпринято действие.
  2. Используйте пользовательское событие для просмотра временных меток и удаления мертвой древесины.

В случае пользователей это будет их выход из системы. В случае чатов это будут те, срок действия которых истек.

0 голосов
/ 24 августа 2011

Кажется, что вас больше всего беспокоит производительность, и у вас есть детали реализации (в основном).Просто измените тип таблицы, которая обрабатывает сеансы, на «память», это уменьшит затраты на производительность запроса базы данных для каждого запроса почти до нуля, поскольку вы извлекаете данные непосредственно из ОЗУ.Просто убедитесь, что вы удаляете сеанс каждый раз, когда пользователь не выходит из системы, или вы помечаете пользователя как неактивного.по HTTP.Но если вы установите разумные тайм-ауты и т. Д., Это будет работать в 99% случаев.

0 голосов
/ 24 августа 2011

Сначала отделите ваши проблемы. Что касается «списка онлайн-пользователей», вы можете использовать базу данных, и, кажется, вы уже поняли это. (даже если кто-то не выйдет из системы должным образом, отображение нескольких дополнительных онлайн-пользователей не принесет большого ущерба)

Теперь для приложения чата, для проверки, если пользователь все еще в сети, вам придется использовать ajax. Другого пути просто нет. Конечно, всегда может быть взлом, я не знаю. см. изображение image, когда вы отвечаете здесь (stackoverflow). Он постоянно проверяет, прошло ли время (и набрали ли вы что-нибудь новое), и сохраняет копию.

0 голосов
/ 24 августа 2011

Большая часть данных, которые вы используете в настоящее время, и необходимые данные хранятся в сеансе PHP - просто не очевидно, как извлечь идентификатор пользователя из информации.

Если вы переключитесь на использование обработчика сеанса, связанного с базой данных, тогда все станет очень просто. У меня был быстрый Google - и есть много примеров там. но многие из них (например, этот ) не проверяют срок действия при повторном чтении сеанса. OTOH пример, на который я ссылался, показывает добавление идентификатора пользователя в запись сессии - что вам понадобится позже. Таким образом, функция обработчика чтения сеанса должна выглядеть примерно так:

 read:
 SELECT session_data, username
 FROM sessions
 WHERE session_id=' . session_id() . '
 AND last_updated>= ' . date('YmdHis', time()-ini_get('session.gc_maxlifetime'))

И чтобы получить всех зарегистрированных пользователей:

 SELECT username
 FROM sessions
 WHERE last_updated>= ' . date('YmdHis', time()-ini_get('session.gc_maxlifetime'))

... и пусть (переопределенный) сборщик мусора сеанса автоматически удаляет избыточные данные.

НТН

0 голосов
/ 24 августа 2011

Я не уверен, что вам нужен делитель вероятности и , но вот что я делаю для автоматического выхода из системы:

ini_set('session.gc_maxlifetime',3600); // 1 hour
ini_set('session.gc_probability',1); // it does garbage cleaning EVERY time
ini_set('session.gc_divisor',1); // it does garbage cleaning EVERY time
session_start();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...