Внедрение обновлений данных в реальном времени в приложениях Mvc с помощью Signalr

Потребность в данных в реальном времени в современных приложениях MVC

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

ASP.NET MVC обеспечивает прочную основу для создания веб-приложений, предоставляемых сервером, но не был разработан для push-коммуникации между сервером и клиентом. Чтобы преодолеть этот разрыв, Microsoft представила SignalR, библиотеку, которая беспрепятственно обеспечивает двунаправленную связь в реальном времени между сервером и клиентами. При интеграции в приложение MVC SignalR позволяет серверу передавать данные подключенным клиентам в момент его появления, устраняя необходимость в опросе и значительно улучшая пользовательский опыт.

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

Понимание архитектуры SignalR

Модель Хаба

SignalR использует абстракцию Hub для управления связью между сервером и подключенными клиентами. Хаб — это класс, который наследует от базового класса . Он определяет методы, которые клиенты могут вызывать удаленно, и предоставляет сильно типизированный API для вызова методов на всех подключенных клиентах, конкретных группах или отдельных клиентах. Под капотом SignalR обрабатывает сериализацию сообщений, отправку и маршрутизацию, поэтому вы можете сосредоточиться на логике приложений, а не на низкоуровневых сетевых деталях.

Транспортные механизмы и Fallback

SignalR поддерживает несколько транспортных протоколов для обеспечения совместимости в разных браузерах и сетевых средах. Основной транспорт - это WebSocket, который предлагает наименьшую задержку и полнодуплексную связь. Когда WebSocket недоступен (из-за ограничений прокси, старых браузеров или брандмауэров), SignalR автоматически возвращается к событиям сервера-отправителя , затем к Forever Frame (для Internet Explorer), и, наконец, к Долгое голосование в качестве последнего средства. Это автоматическое согласование делает SignalR надежным выбором для функций в реальном времени в различных сценариях развертывания.

Переговоры о транспорте происходят во время первого рукопожатия соединения. Клиент отправляет запрос на переговоры, а сервер отвечает списком поддерживаемых транспортов. Затем клиент сначала пытается подключиться с помощью наиболее способного транспорта. Этот процесс прозрачен для вашего кода приложения, но понимание этого помогает при отладке проблем подключения или оптимизации для сред, предназначенных только для WebSocket.

Жизненный цикл подключения

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

Настройка SignalR в приложении ASP.NET MVC

Установка требуемых пакетов

Первым шагом является добавление пакета SignalR NuGet в ваш проект MVC. Вы можете сделать это через консоль диспетчера пакетов или интерфейс диспетчера пакетов NuGet. Для приложений MVC 5 используйте . Этот пакет включает в себя как серверные компоненты, так и клиентскую библиотеку JavaScript. Если вы планируете использовать фреймворк JavaScript или клиент, не являющийся Microsoft, вы также можете установить клиент JavaScript отдельно: .

После установки убедитесь, что в вашем проекте присутствуют следующие файлы:

  • – библиотека на стороне клиента
  • – неминифицированная версия для отладки

Регистрация SignalR в OWIN Startup

ASP.NET MVC 5 использует OWIN для промежуточного ПО. SignalR необходимо настроить в классе запуска OWIN. Если в вашем проекте еще нет файла , добавьте его и включите следующий код:

using Microsoft.Owin;
using Owin;
using YourNamespace; // Replace with your project's namespace

[assembly: OwinStartup(typeof(Startup))]

public class Startup
{
 public void Configuration(IAppBuilder app)
 {
 // Any other OWIN middleware configuration can go here.
 app.MapSignalR();
 }
}

Звонок регистрирует промежуточное ПО SignalR и отображает маршрут концентратора по умолчанию на . Вы можете настроить маршрут, пройдя объект , но для большинства приложений по умолчанию достаточно.

Настройка Global.asax для проектов Pre-OWIN (Legacy)

Если вы используете более старый проект MVC, который не поддерживает OWIN, вы можете настроить SignalR в методе , позвонив . Однако этот подход обесценивается в пользу OWIN. Для новой разработки всегда используйте метод запуска OWIN.

Создание хаба и общение с клиентами

Серверный помощник Hub Class

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

using Microsoft.AspNet.SignalR;
using System.Threading.Tasks;

public class LiveDataHub : Hub
{
 public async Task SendNotification(string userId, string message)
 {
 // Optionally perform server-side validation or storage
 await Clients.User(userId).receiveNotification(message);
 }

 public override Task OnConnected()
 {
 // You can associate the connection with a user/group here
 return base.OnConnected();
 }
}

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

Клиентская интеграция JavaScript

На стороне клиента, включите библиотеку JavaScript SignalR и автоматически генерируемый прокси-скрипт на . Прокси-скрипт динамически генерируется сервером и обеспечивает строго типизированный доступ к вашим методам концентратора. Вот типичная настройка клиента:

<script src="~/Scripts/jquery.signalR-2.4.2.min.js"></script>
<script src="~/signalr/hubs"></script>
<script>
 $(function () {
 // Reference the auto-generated proxy for the hub
 var liveDataHub = $.connection.liveDataHub;

 // Define a client-side method that the hub can call
 liveDataHub.client.receiveNotification = function (message) {
 $('#notifications').append('<p>' + message + '</p>');
 };

 // Start the connection
 $.connection.hub.start().done(function () {
 console.log('Connected to SignalR hub.');
 // Optionally call a server method after connection is established
 // liveDataHub.server.sendNotification('user1', 'Hello from client!');
 }).fail(function (error) {
 console.error('SignalR connection failed: ' + error);
 });
 });
</script>

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

Методы вызова сервера от клиента

Для вызова серверного метода от клиента используйте объект . Например, вызовите метод , определенный выше:

$('#sendButton').click(function () {
 liveDataHub.server.sendNotification($('#userId').val(), $('#messageInput').val());
});

SignalR автоматически сериализует параметры с помощью JSON.Серверный метод работает на пуле потоков сервера, и любые исключения возвращаются клиенту.

Данные вещания из кода Server-Side

От контроллеров и фоновых задач

Концентраторы SignalR обычно вызываются из действий контроллера, фоновых служб или других компонентов на стороне сервера. Чтобы отправлять обновления в реальном времени из-за пределов метода концентратора, вам нужно получить ссылку на контекст концентратора. Это делается с использованием :

public class DataController : Controller
{
 public ActionResult Refresh()
 {
 // Simulate a data update
 string newData = GetLatestData();

 // Get the hub context and broadcast to all connected clients
 var hubContext = GlobalHost.ConnectionManager.GetHubContext<LiveDataHub>();
 hubContext.Clients.All.receiveUpdate(newData);

 return Json(new { success = true });
 }
}

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

Использование фоновых сервисов с SignalR

В современных приложениях ASP.NET MVC можно интегрировать SignalR с BackgroundService или Hosted Services (если использовать ASP.NET Core; для MVC 5 можно использовать через OWIN-хостинг или простой фоновый поток). Например, служба, которая следит за базой данных для изменений, может транслировать обновления при появлении новых записей. Образец тот же: впрыскивайте контекст концентратора и вызовите методы на нем.

Расширенные возможности SignalR

Использование групп для выборочного вещания

Часто требуется отправлять обновления подмножеству пользователей, а не всем. SignalR поддерживает группы, которыми можно управлять на сервере. Клиенты могут присоединяться или покидать группы, вызывая методы в хабе:

public class ChatHub : Hub
{
 public async Task JoinRoom(string roomName)
 {
 await Groups.Add(Context.ConnectionId, roomName);
 }

 public async Task LeaveRoom(string roomName)
 {
 await Groups.Remove(Context.ConnectionId, roomName);
 }

 public void SendToRoom(string roomName, string message)
 {
 Clients.Group(roomName).receiveMessage(message);
 }
}

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

Пользовательские сообщения с аутентификацией

SignalR естественным образом интегрируется с идентификатором ASP.NET. Когда пользователь аутентифицирован, контекст концентратора раскрывает , и личность пользователя автоматически связана с соединением. SignalR предоставляет , который отображает идентификаторы соединения для пользователей на основе интерфейса . По умолчанию он использует имя пользователя. Затем вы можете отправлять сообщения конкретному пользователю, используя .

Чтобы отправить сообщение текущему аутентифицированному пользователю из метода концентратора:

public class PrivateMessagingHub : Hub
{
 public void SendPrivateMessage(string toUser, string message)
 {
 string fromUser = Context.User.Identity.Name;
 Clients.User(toUser).receivePrivateMessage(fromUser, message);
 }
}

Аутентификация необходима для многих функций в реальном времени, таких как персонализированные уведомления или прямые потоки данных, специфичные для пользователя. Убедитесь, что вы настраиваете аутентификацию (куки, токены) до установления соединения SignalR.

Скриншоты из игры Scaling Out with a Backplane

Когда ваше приложение работает на нескольких серверах (веб-ферма), вам нужен backplane для синхронизации сообщений между серверами. SignalR поддерживает несколько провайдеров backplane: Redis, SQL Server, Azure Service Bus и пользовательские реализации. Backplane работает, публикуя все сообщения с любого сервера на backplane, который затем перераспространяет их на все другие серверы в ферме.

Чтобы включить заднюю плоскость Redis, установите и настройте ее в запуске OWIN:

app.MapSignalR(new HubConfiguration()
{
 EnableDetailedErrors = false
});

GlobalHost.DependencyResolver.UseRedis(new RedisScaleoutOptions("connectionString", "yourApp"));

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

Производительность и лучшие практики

Минимизируйте вызовы Hub

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

Используйте эффективную сериализацию

SignalR использует JSON для сериализации по умолчанию. Хотя это удобно, JSON может быть многословным. Если вам нужна максимальная производительность, рассмотрите возможность использования протокола MessagePack для SignalR, который производит меньшие полезные нагрузки и уменьшает использование процессора. Для этого требуется пакет и совместимая клиентская библиотека.

Управляйте отключениями клиентов изящно

Всегда реализуйте логику переподключения на стороне клиента. Клиент JavaScript SignalR имеет встроенное переподключение, но вы можете настроить интервалы повторного подключения и максимальные попытки. На стороне сервера переопределить для очистки ресурсов (например, удалить пользователя из групп, отменить долгосрочные задачи, связанные с этим соединением). Неспособность сделать это может привести к утечкам памяти и устаревшим данным.

Рассмотрите размер и частоту сообщений

Отправка очень больших сообщений (например, мегабайт данных) через SignalR не рекомендуется, поскольку она блокирует транспорт и увеличивает задержку для других клиентов. Если вам нужно отправить большие файлы, используйте отдельный механизм, такой как разрезанная загрузка или выделенные конечные точки. Для частых небольших обновлений убедитесь, что данные сжаты, если это необходимо, особенно через WebSocket.

Реальные примеры и примеры использования

Live Dashboards и мониторинг

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

Мгновенные уведомления

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

Совместное редактирование и Whiteboarding

Приложения, требующие от нескольких пользователей совместной работы над общим документом или холстом, выигрывают от низкой задержки SignalR. Каждое редактирование транслируется всем сотрудникам в режиме реального времени. Для решения конфликтов можно реализовать Operational Transformation или Conflict-Free Replicated Data Types (CRDT) на сервере, но транспорт в реальном времени обеспечивается SignalR.

Акции Ticker и живые ценовые корма

Финансовые приложения часто требуют субсекундных обновлений цен на акции или курсов валют. SignalR может обрабатывать тысячи одновременных подключений и выталкивать обновления, как только они поступают из ленты данных. Используя группы, вы можете позволить пользователям подписываться на конкретные инструменты, уменьшая объем сообщений, которые получает каждый клиент.

Сравнение SignalR с другими технологиями реального времени

Сырой WebSocket

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

Socket.IO (Node.js)

Socket.IO является эквивалентом SignalR для экосистем Node.js. Если ваше приложение построено на Node.js, Socket.IO предлагает аналогичный автоматический резервный транспорт и управление комнатами. Однако для команды, ориентированной на .NET, которая использует ASP.NET MVC, SignalR более естественно интегрируется с существующей инфраструктурой и инструментами.

База данных Firebase Realtime

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

Заключение

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

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

Для дальнейшего чтения изучите официальные ресурсы: ASP.NET SignalR Documentation, SignalR Scaleout with Redis и SignalR Hubs API Guide.