Реалтайм: SignalR и SSE

↑ 3.5 Инфраструктура приложения: ошибки, health checks, фоновые задачи · ← Предыдущая

Обязательно~3 мин чтенияУровень: middle

Зачем это на собесе

Выбор между WebSocket, SignalR, SSE и polling по требованиям и масштабированию.

Объяснение

ТехнологияНаправлениеОсобенности
Polling / long pollingклиент → серверпросто, лишняя нагрузка
SSEсервер → клиентHTTP, авто-переподключение, только текст
WebSocketдвустороннийнизкий уровень, свой протокол сообщений
SignalRдвустороннийабстракция: WebSocket/SSE/long polling, хабы, группы
public class NotificationsHub : Hub
{
    public override async Task OnConnectedAsync()
    {
        await Groups.AddToGroupAsync(Context.ConnectionId, $"user-{Context.UserIdentifier}");
        await base.OnConnectedAsync();
    }
}
 
builder.Services.AddSignalR();
app.MapHub<NotificationsHub>("/hubs/notifications");
 
// отправка из сервиса
await hub.Clients.Group($"user-{userId}").SendAsync("orderUpdated", dto);

Масштабирование

При нескольких инстансах клиенты на разных серверах не видят друг друга: нужен backplane (Redis, Azure SignalR) и sticky sessions либо только WebSocket.

SSE

app.MapGet("/events", (CancellationToken ct) =>
    TypedResults.ServerSentEvents(GetEvents(ct), eventType: "tick"));

Проще, чем SignalR, если нужен только поток от сервера (уведомления, прогресс).

Нюансы и подводные камни

  • Аутентификация WebSocket: токен в query string (для браузерного WebSocket нельзя задать заголовки) — берегите от логирования.
  • Лимиты соединений и память: каждое соединение живёт долго.
  • Proxy должен поддерживать Upgrade и большие таймауты.
  • Сообщения не гарантируют доставку — при переподключении клиент должен запросить пропущенное.

Практика

  1. Сделайте уведомление о смене статуса заказа через SignalR.
  2. Добавьте Redis backplane и запустите два инстанса.
  3. Сравните SSE и SignalR для потока прогресса.

Вопросы с ответами

Связанные темы