ASP.NET Core SignalR hosting i skalowanieASP.NET Core SignalR hosting and scaling

Autorzy Andrew Stanton-pielęgniarki, Brady Gasterai Tomasz DykstraBy Andrew Stanton-Nurse, Brady Gaster, and Tom Dykstra

W tym artykule wyjaśniono zagadnienia dotyczące hostingu i skalowania dla aplikacji o dużym natężeniu ruchu, które używają ASP.NET Core SignalR .This article explains hosting and scaling considerations for high-traffic apps that use ASP.NET Core SignalR.

Sesje programu StickySticky Sessions

SignalR wymaga, aby wszystkie żądania HTTP dotyczące określonego połączenia były obsługiwane przez ten sam proces serwera.SignalR requires that all HTTP requests for a specific connection be handled by the same server process. Gdy SignalR program jest uruchomiony w farmie serwerów (na wielu serwerach), należy użyć "sesji programu Sticky Notes".When SignalR is running on a server farm (multiple servers), "sticky sessions" must be used. "Sesje programu Sticky Notes" są również nazywane koligacją sesji przez niektóre moduły równoważenia obciążenia."Sticky sessions" are also called session affinity by some load balancers. Azure App Service używa routingu żądań aplikacji (ARR) do przesyłania żądań.Azure App Service uses Application Request Routing (ARR) to route requests. Włączenie ustawienia "koligacja ARR" w Azure App Service spowoduje włączenie "sesji programu Sticky Notes".Enabling the "ARR Affinity" setting in your Azure App Service will enable "sticky sessions". Jedyną sytuacją, w której nie są wymagane sesje programu Sticky, są:The only circumstances in which sticky sessions are not required are:

  1. W przypadku hostowania na jednym serwerze w ramach jednego procesu.When hosting on a single server, in a single process.
  2. W przypadku korzystania z SignalR usługi platformy Azure.When using the Azure SignalR Service.
  3. Gdy wszyscy klienci są skonfigurowani do korzystania tylko z obiektów WebSockets, a ustawienie SkipNegotiation jest włączone w konfiguracji klienta.When all clients are configured to only use WebSockets, and the SkipNegotiation setting is enabled in the client configuration.

We wszystkich innych przypadkach (w tym gdy jest używany plan Redis), środowisko serwera musi być skonfigurowane dla sesji programu Sticky Notes.In all other circumstances (including when the Redis backplane is used), the server environment must be configured for sticky sessions.

Aby uzyskać wskazówki dotyczące konfigurowania Azure App Service dla programu SignalR , zobacz Publikowanie aplikacji ASP.NET Core SignalR w Azure App Service .For guidance on configuring Azure App Service for SignalR, see Publikowanie aplikacji ASP.NET Core SignalR w Azure App Service.

Zasoby połączenia TCPTCP connection resources

Liczba współbieżnych połączeń TCP, które może obsługiwać serwer sieci Web, jest ograniczona.The number of concurrent TCP connections that a web server can support is limited. Klienci standardowi HTTP korzystają z połączeń tymczasowych .Standard HTTP clients use ephemeral connections. Te połączenia można zamknąć, gdy klient przechodzi w stan bezczynności i zostanie otwarty ponownie później.These connections can be closed when the client goes idle and reopened later. Z drugiej strony SignalR połączenie jest trwałe .On the other hand, a SignalR connection is persistent . SignalR połączenia pozostają otwarte nawet wtedy, gdy klient przejdzie w stan bezczynności.SignalR connections stay open even when the client goes idle. W aplikacji o dużym natężeniu ruchu, która obsługuje wielu klientów, te trwałe połączenia mogą spowodować, że serwery osiągnął maksymalną liczbę połączeń.In a high-traffic app that serves many clients, these persistent connections can cause servers to hit their maximum number of connections.

Połączenia trwałe zużywają także dodatkową pamięć, aby śledzić każde połączenie.Persistent connections also consume some additional memory, to track each connection.

Duże wykorzystanie zasobów związanych z połączeniami przez SignalR program może mieć wpływ na inne aplikacje sieci Web, które są hostowane na tym samym serwerze.The heavy use of connection-related resources by SignalR can affect other web apps that are hosted on the same server. W przypadku SignalR otwarcia i przechowywania ostatnich dostępnych połączeń TCP inne aplikacje sieci Web na tym samym serwerze również nie będą miały dostępnych połączeń.When SignalR opens and holds the last available TCP connections, other web apps on the same server also have no more connections available to them.

Jeśli na serwerze wykorzystano połączenia, zobaczysz losowe błędy gniazda i błędy resetowania połączenia.If a server runs out of connections, you'll see random socket errors and connection reset errors. Przykład:For example:

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

Aby zapobiec SignalR wykorzystaniu przez zasoby błędów w innych aplikacjach sieci Web, uruchom SignalR na różnych serwerach niż inne aplikacje sieci Web.To keep SignalR resource usage from causing errors in other web apps, run SignalR on different servers than your other web apps.

Aby zapobiec SignalR wykorzystaniu przez zasoby błędów w SignalR aplikacji, Przeskaluj w poziomie, aby ograniczyć liczbę połączeń, które serwer musi obsłużyć.To keep SignalR resource usage from causing errors in a SignalR app, scale out to limit the number of connections a server has to handle.

Skalowanie w poziomieScale out

Aplikacja, która korzysta SignalR z programu, musi śledzić wszystkie połączenia, które tworzą problemy dla farmy serwerów.An app that uses SignalR needs to keep track of all its connections, which creates problems for a server farm. Dodaj serwer i pobiera nowe połączenia, o których nie wie inne serwery.Add a server, and it gets new connections that the other servers don't know about. Na przykład SignalR na każdym serwerze na poniższym diagramie nie można wypróbować połączeń na innych serwerach.For example, SignalR on each server in the following diagram is unaware of the connections on the other servers. Gdy SignalR na jednym z serwerów chce wysłać komunikat do wszystkich klientów, komunikat zostanie przekierowany do klientów podłączonych do tego serwera.When SignalR on one of the servers wants to send a message to all clients, the message only goes to the clients connected to that server.

Skalowanie::: No-Loc (sygnalizujący)::: bez planu

Opcjami rozwiązywania tego problemu jest SignalR usługa platformy Azure i Redis plan.The options for solving this problem are the Azure SignalR Service and Redis backplane.

Usługa platformy Azure SignalRAzure SignalR Service

Usługa platformy Azure SignalR to serwer proxy, a nie plan.The Azure SignalR Service is a proxy rather than a backplane. Za każdym razem, gdy klient inicjuje połączenie z serwerem, klient zostaje przekierowany do programu w celu nawiązania połączenia z usługą.Each time a client initiates a connection to the server, the client is redirected to connect to the service. Ten proces przedstawiono na poniższym diagramie:That process is illustrated in the following diagram:

Nawiązywanie połączenia z platformą Azure::: No-Loc (Sygnalizującer)::: Service

Wynika to z tego, że usługa zarządza wszystkimi połączeniami klientów, natomiast każdy serwer potrzebuje tylko małej stałej liczby połączeń z usługą, jak pokazano na poniższym diagramie:The result is that the service manages all of the client connections, while each server needs only a small constant number of connections to the service, as shown in the following diagram:

Klienci połączeni z usługą, serwery połączone z usługą

Takie podejście do skalowania w poziomie ma kilka korzyści w porównaniu z Redisą dla planu wieloplanowego:This approach to scale-out has several advantages over the Redis backplane alternative:

  • Sesje programu Sticky Notes, nazywane również koligacją klienta, nie są wymagane, ponieważ klienci są natychmiast przekierowywani do SignalR usługi platformy Azure po nawiązaniu połączenia.Sticky sessions, also known as client affinity, is not required, because clients are immediately redirected to the Azure SignalR Service when they connect.
  • SignalRAplikacja może skalować w poziomie na podstawie liczby wysłanych komunikatów, natomiast SignalR usługa Azure skaluje się do obsługi dowolnej liczby połączeń.A SignalR app can scale out based on the number of messages sent, while the Azure SignalR Service scales to handle any number of connections. Na przykład mogą istnieć tysiące klientów, ale jeśli są wysyłane tylko kilka komunikatów na sekundę, SignalR aplikacja nie będzie musiała skalować w poziomie do wielu serwerów, aby obsługiwać same połączenia.For example, there could be thousands of clients, but if only a few messages per second are sent, the SignalR app won't need to scale out to multiple servers just to handle the connections themselves.
  • SignalRAplikacja nie będzie używać znacznie większej liczby zasobów połączenia niż aplikacja internetowa bez SignalR .A SignalR app won't use significantly more connection resources than a web app without SignalR.

Z tego względu zalecamy korzystanie z usługi platformy Azure SignalR dla wszystkich ASP.NET Core SignalR aplikacji hostowanych na platformie Azure, w tym App Service, maszyn wirtualnych i kontenerów.For these reasons, we recommend the Azure SignalR Service for all ASP.NET Core SignalR apps hosted on Azure, including App Service, VMs, and containers.

Aby uzyskać więcej informacji, Zobacz SignalR dokumentację usługi platformy Azure.For more information see the Azure SignalR Service documentation.

Płyta montażowa RedisRedis backplane

Redis to magazyn kluczy w pamięci, który obsługuje system obsługi komunikatów z modelem publikowania/subskrybowania.Redis is an in-memory key-value store that supports a messaging system with a publish/subscribe model. SignalRPlan Redis używa funkcji pub/sub do przesyłania dalej komunikatów do innych serwerów.The SignalR Redis backplane uses the pub/sub feature to forward messages to other servers. Gdy klient nawiązuje połączenie, informacje o połączeniu są przesyłane do planu.When a client makes a connection, the connection information is passed to the backplane. Gdy serwer chce wysłać komunikat do wszystkich klientów, wysyła do planu.When a server wants to send a message to all clients, it sends to the backplane. W planie dla wszystkich podłączonych klientów i serwerów, na których się znajdują.The backplane knows all connected clients and which servers they're on. Wysyła komunikat do wszystkich klientów za pośrednictwem odpowiednich serwerów.It sends the message to all clients via their respective servers. Ten proces przedstawiono na poniższym diagramie:This process is illustrated in the following diagram:

Redis, wiadomości wysyłane z jednego serwera do wszystkich klientów

Plan Redis to zalecane podejście skalowalne w poziomie dla aplikacji hostowanych we własnej infrastrukturze.The Redis backplane is the recommended scale-out approach for apps hosted on your own infrastructure. Jeśli istnieje duże opóźnienie połączenia między centrum danych i centrum danych platformy Azure, SignalR usługa Azure może nie być praktyczną opcją dla aplikacji lokalnych z małymi opóźnieniami lub z wymaganiami dotyczącymi dużej przepływności.If there is significant connection latency between your data center and an Azure data center, Azure SignalR Service may not be a practical option for on-premises apps with low latency or high throughput requirements.

SignalRWymienione wcześniej zalety usługi platformy Azure są niekorzystne dla planu Redis:The Azure SignalR Service advantages noted earlier are disadvantages for the Redis backplane:

  • Wymagane są sesje programu Sticky Notes, znane także jako koligacja klienta, z wyjątkiem sytuacji, gdy spełnione są obie następujące sytuacje:Sticky sessions, also known as client affinity, is required, except when both of the following are true:
    • Wszyscy klienci są skonfigurowani do korzystania tylko z obiektów WebSockets.All clients are configured to only use WebSockets.
    • Ustawienie SkipNegotiation jest włączone w konfiguracji klienta.The SkipNegotiation setting is enabled in the client configuration. Po zainicjowaniu połączenia na serwerze połączenie musi pozostać na tym serwerze.Once a connection is initiated on a server, the connection has to stay on that server.
  • SignalRAplikacja musi być skalowana w poziomie na podstawie liczby klientów, nawet jeśli jest wysyłanych kilka komunikatów.A SignalR app must scale out based on number of clients even if few messages are being sent.
  • SignalRAplikacja używa znacznie większej liczby zasobów połączenia niż aplikacja internetowa bez SignalR .A SignalR app uses significantly more connection resources than a web app without SignalR.

Ograniczenia usług IIS w systemie operacyjnym Windows ClientIIS limitations on Windows client OS

Windows 10 i Windows 8. x są systemami operacyjnymi klienta.Windows 10 and Windows 8.x are client operating systems. Program IIS w systemach operacyjnych klienta ma limit 10 współbieżnych połączeń.IIS on client operating systems has a limit of 10 concurrent connections. SignalRpołączenia:SignalR's connections are:

  • Przejściowe i często ponownie nawiązane.Transient and frequently re-established.
  • Nie usunięto natychmiast, gdy nie jest już używane.Not disposed immediately when no longer used.

Powyższe warunki mogą spowodować osiągnięcie 10 limitów połączeń w systemie operacyjnym klienta.The preceding conditions make it likely to hit the 10 connection limit on a client OS. Gdy system operacyjny klienta jest używany do programowania, zalecamy:When a client OS is used for development, we recommend:

  • Należy unikać usług IIS.Avoid IIS.
  • Użyj Kestrel lub IIS Express jako celów wdrożenia.Use Kestrel or IIS Express as deployment targets.

System Linux z serwerem NginxLinux with Nginx

Poniżej znajdują się minimalne wymagane ustawienia umożliwiające włączenie obiektów WebSockets, ServerSentEvents i LongPolling dla SignalR :The following contains the minimum required settings to enable WebSockets, ServerSentEvents, and LongPolling for 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;

      # 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;
    }
  }
}

Gdy używane są wiele serwerów zaplecza, należy dodać sesje programu Sticky, aby uniemożliwić nawiązywanie SignalR połączeń z serwerów podczas nawiązywania połączenia.When multiple backend servers are used, sticky sessions must be added to prevent SignalR connections from switching servers when connecting. Istnieje wiele sposobów dodawania sesji programu Sticky Nginx.There are multiple ways to add sticky sessions in Nginx. Poniżej przedstawiono dwa podejścia w zależności od tego, co jest dostępne.Two approaches are shown below depending on what you have available.

Dodano następujące elementy oprócz poprzedniej konfiguracji.The following is added in addition to the previous configuration. W poniższych przykładach backend jest nazwą grupy serwerów.In the following examples, backend is the name of the group of servers.

W programie Nginx Open SourceUżyj metody ip_hash do kierowania połączeń do serwera na podstawie adresu IP klienta:With Nginx Open Source, use ip_hash to route connections to a server based on the client's IP address:

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

    ip_hash;
  }
}

Za pomocą programu Nginx Plus sticky Dodaj cookie do żądania i Przypnij żądania użytkownika do serwera:With Nginx Plus, use sticky to add a cookie to requests and pin the user's requests to a server:

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

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

Na koniec przejdź proxy_pass http://localhost:5000 server do sekcji do proxy_pass http://backend .Finally, change proxy_pass http://localhost:5000 in the server section to proxy_pass http://backend.

Aby uzyskać więcej informacji na temat obiektów WebSockets za pośrednictwem usługi Nginx, zobacz Nginx jako serwer proxy protokołu WebSocket.For more information on WebSockets over Nginx, see NGINX as a WebSocket Proxy.

Aby uzyskać więcej informacji o równoważeniu obciążenia i sesjach Nginx, zobacz równoważenie obciążenia sieciowego.For more information on load balancing and sticky sessions, see NGINX load balancing.

Aby uzyskać więcej informacji na temat ASP.NET Core za pomocą Nginx, zobacz następujący artykuł:For more information about ASP.NET Core with Nginx see the following article:

Dostawcy rozwiązań innych firm SignalRThird-party SignalR backplane providers

Następne krokiNext steps

Więcej informacji można znaleźć w następujących zasobach:For more information, see the following resources: