ASP.NET Основное SignalR размещение и масштабирование

Эндрю Стэнтон-Медсестра, Брэди Гастер, и Том Дайкстра

В этой статье описываются рекомендации по размещению и масштабированию приложений с высоким трафиком, которые используют ASP.NET Core SignalR.

Липкие сеансы

SignalR требует, чтобы все HTTP-запросы для определенного подключения обрабатывались тем же процессом сервера. При SignalR запуске на ферме серверов (нескольких серверах) необходимо использовать "липкие сеансы". "Липкие сеансы" также называются сопоставлением сеансов некоторыми подсистемами балансировки нагрузки. использует службу приложение AzureМаршрутизация запросов приложений (ARR) для маршрутизации запросов. Включение параметра ARR Affinity в службе приложение Azure включает "липкие сеансы". Единственными обстоятельствами, в которых не требуются липкие сеансы:

  1. При размещении на одном сервере в одном процессе.
  2. При использовании службы Azure SignalR .
  3. Если все клиенты настроены только для использования WebSockets, апараметр SkipNegotiation включен в конфигурации клиента.

Во всех других обстоятельствах (включая использование серверного плана Redis), среда сервера должна быть настроена для липких сеансов.

Инструкции по настройке службы SignalRприложение Azure см. в статье "Публикация приложения ASP.NET Core SignalR в службе приложение Azure". Рекомендации по настройке липких сеансов для Blazor приложений, использующих службу AzureSignalR, см. в статье "Узел" и развертывание приложений на стороне Blazorсервера ASP.NET Core.

Ресурсы TCP-подключения

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

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

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

Если у сервера не было подключений, вы увидите ошибки случайного сокета и ошибки сброса подключения. Например:

An attempt was made to access a socket in a way forbidden by its access permissions...

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

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

Горизонтальное увеличение масштаба

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

Scaling SignalR without a backplane

Варианты решения этой проблемы — это серверная планка Службы Azure SignalR и Redis.

Служба Azure SignalR

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

Establishing a connection to the Azure SignalR Service

Результатом является то, что служба управляет всеми клиентскими подключениями, в то время как для каждого сервера требуется только небольшое постоянное количество подключений к службе, как показано на следующей схеме:

Clients connected to the service, servers connected to the service

Этот подход к горизонтальному масштабированию имеет несколько преимуществ по сравнению с альтернативным серверным планом Redis:

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

По этим причинам мы рекомендуем службу Azure SignalR для всех приложений ASP.NET CoreSignalR, размещенных в Azure, включая Служба приложений, виртуальные машины и контейнеры.

Дополнительные сведения см. в документации по службе AzureSignalR.

Канал обмена Redis

Redis — это хранилище ключей в памяти, поддерживающее систему обмена сообщениями с моделью публикации и подписки. Серверная SignalR планка Redis использует функцию pub/sub для пересылки сообщений на другие серверы. При подключении клиент передает сведения о подключении в серверную планку. Когда сервер хочет отправить сообщение всем клиентам, он отправляется в серверную планку. Серверная планка знает все подключенные клиенты и какие серверы они подключены. Он отправляет сообщение всем клиентам через соответствующие серверы. Этот процесс показан на следующей схеме:

Redis backplane, message sent from one server to all clients

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

Преимущества службы Azure SignalR , отмеченные ранее, являются недостатками серверной части Redis:

  • Липкие сеансы, также известные как сходство клиентов, являются обязательными, за исключением случаев, когда оба из следующих значений являются истинными:
    • Все клиенты настроены только для использования WebSockets.
    • Параметр SkipNegotiation включен в конфигурации клиента. После запуска подключения на сервере подключение необходимо остаться на этом сервере.
  • Приложение SignalR должно масштабироваться на основе числа клиентов, даже если отправляется несколько сообщений.
  • Приложение SignalR использует значительно больше ресурсов подключения, чем веб-приложение без SignalR.

Ограничения IIS для клиентской ОС Windows

Windows 10 и Windows 8.x — это клиентские операционные системы. СЛУЖБЫ IIS в клиентских операционных системах имеют ограничение в 10 одновременных подключений. SignalRПодключения:

  • Временные и часто созданные повторно.
  • Не удаляется немедленно, когда больше не используется.

Предыдущие условия позволяют получить ограничение на 10 подключений в клиентской ОС. При использовании клиентской ОС для разработки рекомендуется:

  • Избегайте СЛУЖБ IIS.
  • Используйте Kestrel или IIS Express в качестве целевых объектов развертывания.

Linux с Nginx

Ниже приведены минимальные необходимые параметры для включения WebSockets, ServerSentEvents и LongPolling для SignalR:

http {
  map $http_connection $connection_upgrade {
    "~*Upgrade" $http_connection;
    default keep-alive;
  }

  server {
    listen 80;
    server_name example.com *.example.com;

    # Configure the SignalR Endpoint
    location /hubroute {
      # App server url
      proxy_pass http://localhost:5000;

      # Configuration for WebSockets
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection $connection_upgrade;
      proxy_cache off;
      # WebSockets were implemented after http/1.0
      proxy_http_version 1.1;

      # Configuration for ServerSentEvents
      proxy_buffering off;

      # Configuration for LongPolling or if your KeepAliveInterval is longer than 60 seconds
      proxy_read_timeout 100s;

      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
    }
  }
}

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

В дополнение к предыдущей конфигурации добавляется следующее. В следующих примерах backend — это имя группы серверов.

С помощью Nginx Open Source используйте ip_hash для маршрутизации подключений к серверу на основе IP-адреса клиента:

http {
  upstream backend {
    # App server 1
    server localhost:5000;
    # App server 2
    server localhost:5002;

    ip_hash;
  }
}

С помощью Nginx Plus используйте для sticky добавления cookie запросов и закрепления запросов пользователя на сервер:

http {
  upstream backend {
    # App server 1
    server localhost:5000;
    # App server 2
    server localhost:5002;

    sticky cookie srv_id expires=max domain=.example.com path=/ httponly;
  }
}

Наконец, измените server раздел proxy_pass http://localhost:5000proxy_pass http://backendна .

Дополнительные сведения о WebSockets над Nginx см. в ngINX в качестве прокси-сервера WebSocket.

Дополнительные сведения о балансировке нагрузки и липких сеансах см. в статье о балансировке нагрузки NGINX.

Дополнительные сведения о ASP.NET Core с Nginx см. в следующей статье:

Сторонние SignalR поставщики внутреннего плана

Следующие шаги

Дополнительные сведения см. на следующих ресурсах: