Возможность обновления данных в режиме реального времени на клиенте - PullRequest
2 голосов
/ 18 апреля 2019

У меня есть следующий сценарий, который меня интересует, возможно ли / возможно ли это реализовать. Я прошу прощения, если это считается слишком «широким» вопросом, но я думаю, что SO было бы лучшим местом, чтобы задать это.

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

SELECT SUM(revenue) FROM sales 
WHERE timestamp > NOW() - INTERVAL 1 HOUR
GROUP BY category

Насколько мне известно, существует два основных способа обновления данных для конечного пользователя:

  1. Выполните какой-либо опрос (или аналогичный метод) через определенный интервал, чтобы повторно извлечь данные из запроса. Однако это может стать довольно дорогостоящим в зависимости от сложности / продолжительности запроса и количества людей, подключенных одновременно.
  2. Вторым методом будет сохранение всех данных в памяти и передача обновления непосредственно в это хранилище памяти (которое может быть на стороне клиента или на стороне сервера), и мы можем отправлять запрос ws конечному пользователю всякий раз, когда есть обновление данных. Примером этого может быть что-то вроде https://github.com/jpmorganchase/perspective.

Тогда мой вопрос: возможно ли вообще обновлять данные в реальном времени (случай, который я описываю в Примере 2), когда данные слишком велики для хранения в памяти. Я думаю, что ответ «нет», но, возможно, мне не хватает некоторых способов сделать это. Например, допустим, у меня есть 1 ТБ данных, хранящихся в BigQuery, и я передаю им обновления с покупками новых продуктов - есть ли способ отправить обновления конечному клиенту без необходимости повторного выполнения запроса каждый раз, когда я хотите получить обновление? Есть ли другие технологии, которые могут быть использованы / полезны для этого сценария?

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

Ответы [ 3 ]

0 голосов
/ 28 апреля 2019

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

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

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

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

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

0 голосов
/ 28 апреля 2019

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

График «продажи за последний час» не содержит информации и трудно обновляется.

Обновления должны вычитать продажи по мере продвижения «последнего часа» (с 13:05 до 13:06), а также добавлять новые продажи.

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

Я бы рассмотрел 24-часовой график или 12-часовой график, разделенный на фактические часы.

Это может упростить обновления и, вероятно, даст более полезные метрики.

Таким образом, обновления графика всегда аддитивны, поэтому хранилище данных в памяти не требуется (и информация более активна).

Например, каждая новая продажа может быть опубликована на канале "new_sale". Опубликованные данные о продажах могут включать точное время.

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

0 голосов
/ 22 апреля 2019

Поскольку вас заинтересовал этот вариант, я решил расширить комментарий до ответа.Я возьму SQL Server и C # compoment - sqltabledependency .Вы можете проверить его, если он соответствует вашим потребностям.

  1. Вы бы создали временную таблицу, в которую вы положили бы любые изменения из таблицы sales, например, sales_data_watch (вы могли бы иметь тамтакже агрегации предварительного расчета, как в вашем примере).

  2. Вы создадите почасовую работу, которая будет отслеживать изменения в таблице sales и выполнять вставку / обновление для sales_data_watch

  3. Вы бы подключили зависимость C # sqltable, связанную с sales_data_watch (примечание: взят из примера, чтобы соответствовать вашей таблице)

    public class SaleData
    {
       public int revenue{ get; set; }
    }
    
    public class Program
    {
     private static string _con = "data source=.; initial catalog=MyDB; integrated security=True";
    
     public static void Main()
     {
      // The mapper object is used to map model properties 
      // that do not have a corresponding table column name.
      // In case all properties of your model have same name 
      // of table columns, you can avoid to use the mapper.
      var mapper = new ModelToTableMapper<SaleData>();
      mapper.AddMapping(s => s.revenue, "Aggregated revenue");
    
      // Here - as second parameter - we pass table name: 
      // this is necessary only if the model name is different from table name 
      // (in our case we have Sale vs Sales). 
      // If needed, you can also specifiy schema name.
      using (var dep = new SqlTableDependency<SaleData>(_con, "sales_data_watch", mapper: mapper));
      {
       dep.OnChanged += Changed;
       dep.Start();
    
       Console.WriteLine("Press a key to exit");
       Console.ReadKey();
    
       dep.Stop();
      } 
     }
    
     public static void Changed(object sender, RecordChangedEventArgs<SaleData> e)
     {
      var changedEntity = e.Entity;
    
      Console.WriteLine("DML operation: " + e.ChangeType);
      Console.WriteLine("Revenue: " + changedEntity.Revenue);
     }
    }
    
  4. После того, как все уведомления были распределены, вы можете сделать truncate table sales_data_watch после (если вы не хотите, чтобы таблица стала слишком большой, что в конечном итоге замедлило бы весь процесс.

Этоиспользуя только сервер SQL и компонент C #. Существуют и другие, возможно, лучшие варианты, например: Определить изменение таблицы записей с помощью MVC, SignalR, jQuery и SqlTableDependency , чтобы сделать это по-другому. Это будет зависеть от вашегопредпочтения.

Редактировать полный пример ссылки для Создание диаграмм в реальном времени с Angular 5, Google Charts, SignalR Core, .NET Core 2, Entity Framework Core 2 иSqlTable зависимость (эта ссылка является первой страницей из трех).В верхней части страницы вы можете увидеть график в реальном времени Google.Все кредиты идут на anthonygiretti .Вы можете загрузить пример проекта по адресу github .

Используемые технологии

База данных

Sql Server, localDb с Visual Studio 2017 корректно, чтобы он работал

Front End-технологии

Angular 5
Google Charts
Visual Studio Code
SignalR Client

BackEnd-технологии

.NET Core 2
SignalR Core
EntityFramework Core
EntityFramework Core for Sql Server
SqlTableDependency

Сначала необходимо установить необходимые компоненты - сервисный брокер, SQL Table, Angular-CLI, проект Angular 5,Клиент SignalR (VS 2017, установлен .Net Core 2 SDK) - ссылка та же part1

Далее идет настройка бэкэнда - part2

Чтобы заставить его работать, этот проект содержит:

  • A DbContext (GaugesContext.cs) для EntityFramework Core
  • Концентратор (GaugeHub.cs) для SignalR, передающий данные
  • Модель, содержащая строго типизированные данные для отправки (Gauge.cs)
  • Репозиторий, предоставляемый Entity Framework и его интерфейсом (GaugeRepository.cs и IGaugeRepository.cs)
  • Подписка на Gauge sqlтаблица с SqlTableDependency и ее Interface (GaugeDatabaseSubscription.cs и IDatabaseSubscription)
  • Два метода расширения, расширяющих IServiceCollection (AddDbContextFactory.cs) и IApplicationBuilder (UseSqlTableDependency.cs) и Startup.cs и Program.cs
1085

1085часть заключается в настройке внешнего интерфейса - part3

У нас есть:

  • Папка, содержащая компонент диаграммы датчиков (gaugeschart.component.html и gaugeschart.component.ts)
  • Папка, которая содержит службу диаграмм и базовую службу Google Charts (google-gauges-chart.service.ts и google-charts.base.service.ts)
  • Папка, содержащая файлы окружений
  • Папка, содержащая строго типизированную модель для калибровочной диаграммы (gauge.ts)
  • Наконец, в корне папки src компоненты файлов по умолчанию и модуль (приложение)файлы компонентов и файл модуля приложения)

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

...