Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 07.07.2015, 11:50
Аватар для Gozar
Отправить личное сообщение для Gozar Посмотреть профиль Найти все сообщения от Gozar
 
Регистрация: 07.06.2007
Сообщений: 7,504

синхронизация пользователей (вкладки, сессии...)
Как правильно организовать синхронизацию пользователей?

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

в наличии есть nodejs и socket.io.

Задача синхронизировать пользователей с сервером, обеспечив их чатом, обновлениями сообщений и т.д. при этом по максимуму сократить избыточные операции. В идеале при переходе со страницы на страницу запрос должен идти лишь на соединение socket.io, а запрашиваться инфа должна только в начале сессии и обновляться только тогда, когда сервер говорит: на новую инфу.

Кто-нибудь сталкивался с подобной задачей или видел статьи на эту тему?
__________________
Последний раз редактировалось Gozar, Сегодня в 24:14.
Ответить с цитированием
  #2 (permalink)  
Старый 07.07.2015, 12:08
Аватар для kobezzza
Быдлокодер;)
Отправить личное сообщение для kobezzza Посмотреть профиль Найти все сообщения от kobezzza
 
Регистрация: 19.11.2010
Сообщений: 4,338

Я могу много рассказать про этот кейз, но нужно больше инфы, про твой случай, т.к. паттернов оч много.
__________________
kobezzza
code monkey
Ответить с цитированием
  #3 (permalink)  
Старый 07.07.2015, 12:27
Аватар для Gozar
Отправить личное сообщение для Gozar Посмотреть профиль Найти все сообщения от Gozar
 
Регистрация: 07.06.2007
Сообщений: 7,504

Сообщение от kobezzza
нужно больше инфы
Какой именно?

nodejs+express+nginx. ограничений в устанавливаемом ПО нет.

Хочу, чтобы пользователи при логинизации запрашивали последние обновления (они хранятся в кэше nodejs и отдаются быстро).

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

Самый большой вопрос связан с запросами кто онлайн: когда запрашивать кто онлайн, как узнать что пользователь закрыл браузер|вкладку, как определить что пользователь онлайн, активен, где и как хранить сессию, чтобы работало быстро и не нужно было в течении 1 сессии кидать запрос в базу на чтение инфы о пользователе?

Через socket.io я могу с сервера посылать нужные обновления пользователям, но не понимаю как проверять онлайность.


Предполагаю:
при открытии вкладки(браузера) нужно создавать сессию и отдавать её пользователю
__________________
Последний раз редактировалось Gozar, Сегодня в 24:14.

Последний раз редактировалось Gozar, 07.07.2015 в 12:36.
Ответить с цитированием
  #4 (permalink)  
Старый 07.07.2015, 12:30
Аватар для kobezzza
Быдлокодер;)
Отправить личное сообщение для kobezzza Посмотреть профиль Найти все сообщения от kobezzza
 
Регистрация: 19.11.2010
Сообщений: 4,338

Там все сложнее, вечером постараюсь описать, ща на работе.
__________________
kobezzza
code monkey
Ответить с цитированием
  #5 (permalink)  
Старый 07.07.2015, 12:37
Аватар для Gozar
Отправить личное сообщение для Gozar Посмотреть профиль Найти все сообщения от Gozar
 
Регистрация: 07.06.2007
Сообщений: 7,504

ок, может я до вечера ещё чего надумаю
__________________
Последний раз редактировалось Gozar, Сегодня в 24:14.
Ответить с цитированием
  #6 (permalink)  
Старый 08.07.2015, 21:52
Аватар для kobezzza
Быдлокодер;)
Отправить личное сообщение для kobezzza Посмотреть профиль Найти все сообщения от kobezzza
 
Регистрация: 19.11.2010
Сообщений: 4,338

Вчера пришёл убитый, поэтому пишу только сейчас.

Итак, начнём с самого важного. Главное при работе с сокетами - это заложить горизонтальное масштабирование, хотя пожалуй это главное почти для всего. Дело в том, что у тебя не будет проблем, когда все твои коннекты висят на одном сервере, но если ты допускаешь, что нагрузка будет расти и понадобится кластер, то ты сразу получишь граблемя по лицу, например: чат между двумя юзерами - один работает с одним сервером, другой с другим и поэтому они про друг по друга ничего не знают и нет никакой возможности узнать о новых сообщениях, кроме как время от времени чекать БД, но сам понимаешь, что это плохой способ. Путей решения несколько, начну от простого к сложному.

1) Заюзать сторонний сервис уведомлений (например, https://pusher.com/) и работать по схеме: подключаешь их браузерную либу, клиенты конектятся по сокету к их серверам, а они в свою очередь шлют уведомления на твои сервера, где ты через их серверную либу обрабатываешь их.

Плюсы:

Очень просто реализовать.
Легко масштабировать.

Минусы:

Это платная услуга.
Каждый клиент создаёт коннекшин, а число коннекшинов ограничено тарифами.
Каждый клиент генерирует сообщения, число которых также ограничено тарифом.

2) Заюзать сторонний сервис уведомлений, но в качестве клиента использовать свои сервера, т.е. твои пользователи конектятся напрямую к твоим серверам, а они уже конектятся к API сервиса и шлюс сообщения.

Плюсы:

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


Минусы:

Это платная услуга.

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

Плюсы:

Не надо платить за внешний сервис.
Легко масштабировать (при условии если нормально напишешь).

Минусы:

Это сложнее реализовать.
Появляется дополнительная головная боль, которую сторонний сервис инкапсулирует от нас.

4) WebRTC. Использование P2P подхода может сделать твою систему децентролизованой и значительно облегчить нагрузку на сервер, т.к. он будет рулить рукопожатия клиентов, при необходимости ходить в базу и рассылать сообщения при необходимости.

Плюсы:

Очень сильно сбивает нагрузку на сервер.
Не надо платить за внешний сервис.
Легко масштабировать (при условии если нормально напишешь).

Минусы:

Это сложно реализовать по нормальному.
Постоянный затрах с синхронизацией состояний на разных клиентах.


***

Я юзаю 2-й и 4-й подходы. Следующим постом продолжу лекцию
__________________
kobezzza
code monkey
Ответить с цитированием
  #7 (permalink)  
Старый 08.07.2015, 22:18
Аватар для kobezzza
Быдлокодер;)
Отправить личное сообщение для kobezzza Посмотреть профиль Найти все сообщения от kobezzza
 
Регистрация: 19.11.2010
Сообщений: 4,338

Теперь поговорим про локальную БД. Сразу скажу, что это реально геморой.

Начнём с синхронизации данных между клиентом и сервером. Лучше всего, использовать паттерн версионирования данных, т.е. заводим в нашей коллекции/таблице у документов/строк дополнительные поля, обычно хватает одного, назовём его __v и пускай это будет целое число, которое будет увеличиваться при каждом обновлении записи, и тогда для синхронизации данных будет достаточно прикрепить версию локальных данных в запросе, и если они отличаются, то сервер отдаст новые данные, а если нет - то пустой ответ. Разумеется, когда пользователь обновляет данные, то вместе с ответом сервера, что всё ок, он должен возвращать новую версию __v.

Более подробны про доступные паттерны версионирования можно почитать в книге Фаулера NoSQL.

Теперь про локальные хранилища: не юзай голый local storage, ибо без нормальной абстракции ты рискуешь огрести граблями. Лучше всего заюзать SQLLite (есть порт на asm.js) / IndexedDB (есть во всех современных браузерах) или библиотеку, которая инкапсулирует общения с хранилищем и даёт нормальный интерфейс запросов.

Про синхронизацию событий между вкладками: это геморой, но вообще можно юзать localStorage / sessionStorage и его событие onChange, или заюзать ServiceWorker (это вариант WebWorker, который биндится к домену, а не вкладке).
__________________
kobezzza
code monkey
Ответить с цитированием
  #8 (permalink)  
Старый 08.07.2015, 22:25
Аватар для kobezzza
Быдлокодер;)
Отправить личное сообщение для kobezzza Посмотреть профиль Найти все сообщения от kobezzza
 
Регистрация: 19.11.2010
Сообщений: 4,338

Цитата:
Через socket.io я могу с сервера посылать нужные обновления пользователям, но не понимаю как проверять онлайность.
Заведи отдельную базу типа ключ-значение, например для таких задач ох хорошо подходит Redis, где кешируй эту инфу.
__________________
kobezzza
code monkey
Ответить с цитированием
  #9 (permalink)  
Старый 08.07.2015, 22:26
Аватар для cyber
I am Student
Отправить личное сообщение для cyber Посмотреть профиль Найти все сообщения от cyber
 
Регистрация: 17.12.2011
Сообщений: 4,415

Сообщение от kobezzza
4) WebRTC. Использование P2P подхода может сделать твою систему децентролизованой и значительно облегчить нагрузку на сервер, т.к. он будет рулить рукопожатия клиентов, при необходимости ходить в базу и рассылать сообщения при необходимости.
Опиши подробнее плиз
__________________
Цитата:
Если ограничения и условия описываются как "коробка", то хитрость в том что бы найти именно коробку... Не думайте о чем то глобальном - найдите коробку.
Ответить с цитированием
  #10 (permalink)  
Старый 08.07.2015, 22:32
Аватар для kobezzza
Быдлокодер;)
Отправить личное сообщение для kobezzza Посмотреть профиль Найти все сообщения от kobezzza
 
Регистрация: 19.11.2010
Сообщений: 4,338

Сообщение от cyber Посмотреть сообщение
Опиши подробнее плиз
Ну, WebRTC позволяет общаться клиентам напрямую друг с другом, внешний сервер нужен только для рукопожатия, а дальше вы уже общаетесь сами, а если нужна история сообщений, то фоном время от времени можно дампить инфу на сервер. С помощью WebRTC можно также делать аудио и видео конференции, см например сервис Firefox Hello или либу https://togetherjs.com/
__________________
kobezzza
code monkey
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
совместная работа нескольких пользователей Aeliot@ Элементы интерфейса 5 27.09.2014 00:35
Доступ пользователей к разделу сайта по протоколу https:// Mp98-js Серверные языки и технологии 3 14.10.2013 00:45
Динамические вкладки Tmin10 jQuery 2 07.03.2012 10:48
Ajax добавление в массив сессии kiff86 AJAX и COMET 0 29.10.2011 11:48
IE, как сохранить вкладки Fly_ Internet Explorer 6 03.05.2010 16:00