Как наиболее правильно разработать сервер чата с комнатами на WebSocket?
Здравствуйте.
Имеется база данных (MySQL), в ней таблицы:
--------------‐-------------
- users [id, nickname, key, room_id, ...] (key - ключ для авторизации, room_id - последняя комната, где был пользователь)
- rooms [id, name, user_id, ...] (user_id - владелец комнаты)
--------------‐-------------
Есть два варианта, на каком ЯП писать серверную часть чата, GoLang и Node.JS, т.е., на двух языках написано два черновых варианта, но в двух вариантах встал на месте.
Нужно держать ~5000 человек онлайн.
При каждой авторизации мы лезим в БД (Sequelize/Gorm), проверяем, есть ли такой пользователь, если есть, то получаем информацию о нём, делаем рассылку другим о том, что зашёл новый пользователь (тем, кто в этой же комнате).
Самая главная проблема в том, что есть и дополнительные поля в БД, которые могут периодически меняться от действий пользователей.
Не лезть же каждый раз в БД, чтобы выдать пользователю информацию о других пользователях в его комнате (в которой он на данный момент), о новых параметрах комнаты.
Хранить объекты пользователей в массивах не лучший вариант, наверное. Под такое и адаптер надо писать, чтобы при изменении свойств объекта в массиве менял и в БД. Redis не особо хочется использовать, но под него надо тоже писать адаптер для обновления в БД.
Пожалуйста, кто в этой теме понимает, подскажите, как наиболее правильно всё это дело организовать и как правильно будет держать пользователей в комнатах?
Redis, не бойтесь интегрировать
Шаблоны проектирования Node.js / пер. с анг. А. Н. Киселева. – М.: ДМК Пресс,
2017. – 396 с.: ил.
ISBN 978-5-97060-485-4
С 300 страницы описывают решение подобных проблем
Не лезть же каждый раз в БД, чтобы выдать пользователю информацию о других пользователях в его комнате
?
У тебя websocket, что подразумевает что на клиент передается оперативная информация (изменения) а не полное состояние по таймеру, значит клиент самостоятельно хранит в себе необходимую информацию в коде на javascript в массивах или localstorage, если это так критично
Клиент уже написан, он на java (android) и хранит информацию. Например, один из пользователей поменял никнейм или установил себе какой-нибудь статус, который будет сохраняться при перезаходе в чат и переходе в другую комнату, естественно он должен будет обновиться в БД. Проблема в том, как организовать грамотное хранение пользователей и как постоянно обновлять данные в БД, не создавая огромную нагрузку. Например, подключился новый пользователь по WS, авторизация прошла, нужно закинуть его куда-то, закрепив на ним сокет (соединение), в массив объектов или Redis как новый объект. Я не знаю, как наиболее правильно будет. Но нужно будет быстро находить этого пользователя, по соединению, id, никнейму, быстро менять свойства объекта, не делая перебор массива и чтобы был сброс изменений в БД
в общем случае, без относительно языков фреймворков и т.п. есть два кардинально разных подхода:
* стратегия тонкий клиент, каждый раз, когда тебе нужны данные, делай запрос в базу данных/сервер
* стратегия толстый клиент, клиент хранит все что возможно у себя (вплоть до дублирования функционала сервера), кешируя и отслеживая инвалидацию данных и прочее, красивый вырожденный пример - имея полное состояние базы на каждом клиенте, серверу достаточно пересылать любые события, меняющие эти состояния от клиентов напрямую клиентам (в т.ч. минуя сам сервер, используя p2p), а клиенты синхронно обновляют свое состояние, синхронизируя его друг с другом, используя минимум сетевого взаимодействия (примерно этим подходом пользуются онлайн игры, само собой клиенты хранят только нужный им на текущий момент слепок данных)
По твоим вопросам, да так и делай, это ведь не проблема. redis очень быстрая nosql база данных.
Еще момент, если у тебя websocket сервер, значит веб приложение скорее всего реализовано не http rest принципам а в виде не выгружаемого приложения, а значит многие данные можно не запрашивать постоянно из базы, а хранить в оперативной памяти в глобальных массивах
Между этими двумя подходами нет четкой границы, к примеру можно реализовать тонкий клиент с кешированием данных, для которых контроль инвалидации не критичен или не сильно требует ресурсы или ошибки ожидаемы, весь веб на этом построен.