Застрял на подходе для данных в реальном времени с пользовательскими фильтрами - PullRequest
3 голосов
/ 14 апреля 2020

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

Я делаю приложение, которое предоставляет клиенту данные в реальном времени, я думал о Server-Sent-Events, но это не позволяет -пользовательские ответы AFAIK.

WebSocket также вариант, но я не уверен в этом, позвольте мне набросать мой сценарий, который я сделал с WS:

  1. Сервер выбирает 20 записей каждый во-вторых, и помещает их в массив
  2. Этот массив отправляется во все соединения веб-сокетов каждую секунду, см. это псевдо ниже:
let items = [ { ... some-data ... } ];

io.on("connection", socket => {
  setInterval(() => {
    io.emit("all_items", items);
  }, 1000);
});
Пользователь может выбрать некоторые элементы в интерфейсе, веб-сокет получает это за соединение

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

  • Есть база данных, скажем, 1000 записей
  • Пользователь подключается к фону из (React) Front-end, подключается к основному «потоку» с около 20 извлеченных записей (без фильтров), которые сервер извлекает каждую секунду. SELECT * FROM Items LIMIT 20

Вот сложная часть:

  • Пользователь нажимает некоторые флажки с пользовательскими фильтрами (в интерфейсе), например, location = Shelf 2. Теперь, что должно произойти, это то, что веб-сокет ВСЕГДА показывает 20 записей для этого пользователя, независимо от того, какие фильтры

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

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

1 Ответ

2 голосов
/ 14 апреля 2020

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

Я полагаю, ваш сервер поддерживает около 1 тыс. Точек данных с изменчивыми значениями. (Он может использовать СУБД для поддержания этих значений, но давайте пока что будем игнорировать этот механизм.) Я думаю, какой-то процесс в вашем приложении изменяет эти значения на основе какого-то внешнего стимула.

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

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

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

Предполагается, что приложение будет работать в масштабе со многими подключенными клиентами.

Вот некоторые соображения по проектированию системы.

  1. Храните точки данных в ОЗУ в подходящая структура данных.
  2. Запись js кода для применения клиентских фильтров к этой структуре данных. Если этот код эффективен, вы можете обрабатывать миллионы точек данных таким образом.
  3. Резервное копирование этой структуры данных ОЗУ на СУБД по вашему выбору; MySQL - это хорошо.
  4. Когда сервер впервые запускается, загрузите структуру данных из базы данных.

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

Но, ЯГНИ . Приведите все в порядок, а затем выясните, как их масштабировать. (Это действительно тяжелая работа, чтобы добраться до 10K пользователей; тратьте свое время на то, чтобы сделать ваше приложение превосходным для первых 10, а затем 100 пользователей, а затем увеличить его.)

Взаимодействие вашего сервера с клиентами происходит следующим образом (игнорируя аутентификацию , et c).

  1. Клиент подключается, неявно запрашивая фильтр "без фильтрации".
  2. Клиент получает двадцать значений, выдвигаемых каждую секунду.
  3. Клиент может неявно запросить другой фильтр в любое время.
  4. Затем клиент продолжает получать двадцать значений, выбранных выбранным фильтром.

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

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

  1. Новые клиенты подключаются к конечной точке SSE в https://example.com/stream

  2. При применении фильтра они повторно подключаются к другому Конечная точка SSE в https://example.com/stream?filter1=a&filter2=b&filter3=b

  3. Сервер отправляет данные каждую секунду каждому открытому соединению SSE, применяющему фильтр. (Потоки очень хорошо работают для этого в nodejs; посмотрите, например, код на стороне сервера для пакета signalhub .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...