Распределённый счётчик для веб-приложений

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

Задача

Итак, необходимо учитывать количество пользователей, осуществляющих запросы к веб-приложению, которое расположено на нескольких (n) серверах. Временной лаг обновления статистики составляет $timeout = 10 секунд. Период неактивности пользователя, после которого считаем, что он – офлайн = $timeout.

Вариант решения

1. При поступление запроса на i-ый сервер если считаем хосты, то проверяем есть ли сессия. Если есть, то ничего не делаем, т.к. пользователь уже засчитан в период $timeout.
Если же сессии нет, то инкрементируем буферное значение счетчика в shm (памяти). Если считаем хиты а не хосты, то инкрементируем значение счётчика в любом случае.
Далее выводим на экран значения из основного счётчика. Т.е. все инкременты попадают в буферный счётчик, и они с основным меняются каждые $timeout секунд. Принцип аналогичен тому, как прорисовывается кадр в видеоконтроллере (двойная буферизация).

2. Каждые $timeout минут веб-приложение отсылает основной счётчик на сервер БД в виде кортежа {‘server_id’: $server_i_id, ‘online’: $local_online }. Тут возможны варианты: либо использовать key-value хранилище, либо MySQL с таблицей на движке Memory).
На сервере БД таким образом каждые $timeout минут обновляется табличка, в которой записано количество пользователей онлайн на серверах.
4. Для получения общего количества пользователей веб-приложения надо просуммировать числа в столбце online таблицы(коллекции). Это число возвращается веб-приложению и отображается на странице.
Таким образом на каждом сервере хранятся данные только о его пользователях онлайн, распознавание уникальности пользователя реализовано с помощью сессий, а т.к. у нас распределённое хранение сессий уже наверняка проработано, то с этим проблем не будет.

Если вы знаете другие способы организации распределённых счётчиков – жду ваших мнений в комментах.

Ссылки

Scaling Distributed Counter

9 Comments

    1. Для хранения локальных данных – это Apc, в качестве БД – MongoDb.

      1. в приложении и так использовадось MongoDB или специально для счетчика его делал? Я что-то не понял тогда каким образом у тебя APC стал shm(это же shared memory?)?

          1. На самом деле это скорее умозрительная задача, реализацию я не кодил, но думаю общий принцип описал.

    1. Я даже догадываюсь, где 🙂 Первая буква “m”?

Leave a Comment