Wprowadzenie do skalowania w poziomie w usłudze SignalR

Autor : Patrick Fletcher

Ostrzeżenie

Ta dokumentacja nie jest przeznaczona dla najnowszej wersji usługi SignalR. Przyjrzyj się ASP.NET Core SignalR.

Wersje oprogramowania używane w tym temacie

Poprzednie wersje tego tematu

Aby uzyskać informacje o wcześniejszych wersjach usługi SignalR, zobacz SignalR Older Versions (Starsze wersje usługi SignalR).

Pytania i komentarze

Prześlij opinię na temat tego, jak podoba ci się ten samouczek i co możemy poprawić w komentarzach w dolnej części strony. Jeśli masz pytania, które nie są bezpośrednio związane z samouczkiem, możesz opublikować je na forum ASP.NET SignalR lub StackOverflow.com.

Ogólnie rzecz biorąc, istnieją dwa sposoby skalowania aplikacji internetowej: skalowanie w górę i skalowanie w poziomie.

  • Skalowanie w górę oznacza użycie większego serwera (lub większej maszyny wirtualnej) z większą ilością pamięci RAM, procesorów CPU itp.
  • Skalowanie w poziomie oznacza dodanie większej liczby serwerów do obsługi obciążenia.

Problem ze skalowaniem w górę polega na tym, że szybko osiągniesz limit rozmiaru maszyny. Poza tym należy skalować w poziomie. Jednak podczas skalowania w poziomie klienci mogą być kierowani do różnych serwerów. Klient połączony z jednym serwerem nie będzie odbierał komunikatów wysyłanych z innego serwera.

Diagram przedstawiający strzałki przechodzące z klientów do Load Balancer do serwerów.

Jednym z rozwiązań jest przekazywanie komunikatów między serwerami przy użyciu składnika o nazwie backplane. Po włączeniu planu wstecznego każde wystąpienie aplikacji wysyła komunikaty do planu wstecznego, a plan zaplecza przekazuje je do innych wystąpień aplikacji. (W elektronice płaszczyzna wsteczna jest grupą łączników równoległych. Analogicznie, backplan signalR łączy wiele serwerów).

Diagram przedstawiający strzałki przechodzące z serwera aplikacji Signal R do planu wstecznego do serwera aplikacji Signal R do komputerów.

Usługa SignalR obecnie udostępnia trzy płaszczyzny zaplecza:

  • Azure Service Bus. Service Bus to infrastruktura obsługi komunikatów, która umożliwia składnikom wysyłanie komunikatów w luźny sposób.
  • Redis. Redis to magazyn klucz-wartość w pamięci. Usługa Redis obsługuje wzorzec publikowania/subskrybowania ("pub/sub") na potrzeby wysyłania komunikatów.
  • SQL Server. SQL Server backplane zapisuje komunikaty w tabelach SQL. Plan zaplecza używa usługi Service Broker do wydajnego obsługi komunikatów. Jednak działa również wtedy, gdy usługa Service Broker nie jest włączona.

Jeśli wdrażasz aplikację na platformie Azure, rozważ użycie planu backplanu Redis przy użyciu usługi Azure Redis Cache. Jeśli wdrażasz na własnej farmie serwerów, rozważ SQL Server lub backplany usługi Redis.

Następujące tematy zawierają samouczki krok po kroku dla każdego planu zaplecza:

Implementacja

W usłudze SignalR każda wiadomość jest wysyłana za pośrednictwem magistrali komunikatów. Magistrala komunikatów implementuje interfejs IMessageBus , który zapewnia abstrakcję publikowania/subskrybowania. Samoloty wsteczne działają, zastępując domyślny IMessageBus magistralą zaprojektowaną dla tego backplanu. Na przykład magistrala komunikatów dla usługi Redis to RedisMessageBus i używa mechanizmu pub/sub usługi Redis do wysyłania i odbierania komunikatów.

Każde wystąpienie serwera łączy się z zapleczem za pośrednictwem magistrali. Po wysłaniu komunikatu następuje przejście do planu wstecznego, a plan zaplecza wysyła go na każdy serwer. Gdy serwer otrzymuje komunikat z planu wstecznego, umieszcza komunikat w lokalnej pamięci podręcznej. Następnie serwer dostarcza komunikaty klientom z lokalnej pamięci podręcznej.

Dla każdego połączenia klienta postęp klienta podczas odczytywania strumienia komunikatów jest śledzony przy użyciu kursora. (Kursor reprezentuje pozycję w strumieniu komunikatów). Jeśli klient rozłącza się, a następnie ponownie nawiązuje połączenie, zwraca się do magistrali o wszystkie komunikaty, które dotarły po wartości kursora klienta. Dzieje się tak samo, gdy połączenie używa długiego sondowania. Po zakończeniu długiego żądania sondowania klient otworzy nowe połączenie i poprosi o komunikaty, które dotarły po kursorze.

Mechanizm kursora działa nawet wtedy, gdy klient jest kierowany do innego serwera na ponownym połączeniu. Plan zaplecza jest świadomy wszystkich serwerów i nie ma znaczenia, z którym serwerem nawiązuje połączenie klient.

Ograniczenia

Przy użyciu planu wstecznego maksymalna przepływność komunikatów jest niższa niż wtedy, gdy klienci komunikują się bezpośrednio z jednym węzłem serwera. Dzieje się tak, ponieważ plan zaplecza przekazuje każdy komunikat do każdego węzła, więc plan zaplecza może stać się wąskim gardłem. Czy to ograniczenie jest problemem, zależy od aplikacji. Oto na przykład niektóre typowe scenariusze usługi SignalR:

  • Emisja serwera (np. znacznik giełdowy): samoloty wsteczne działają dobrze w tym scenariuszu, ponieważ serwer kontroluje szybkość wysyłania komunikatów.
  • Klient-klient (np. czat): W tym scenariuszu plan zaplecza może być wąskim gardłem, jeśli liczba komunikatów jest skalowana wraz z liczbą klientów; oznacza to, że jeśli szybkość komunikatów rośnie proporcjonalnie w miarę większa liczby klientów.
  • Czas rzeczywisty o wysokiej częstotliwości (np. gry w czasie rzeczywistym): plan zaplecza nie jest zalecany w tym scenariuszu.

Włączanie śledzenia dla skalowania usługi SignalR

Aby włączyć śledzenie dla backplanes, dodaj następujące sekcje do pliku web.config w obszarze głównego elementu konfiguracji :

<configuration>
  <system.diagnostics>
    <sources>
      <source name="SignalR.SqlMessageBus">
        <listeners>
          <add name="SignalR-Bus" />
        </listeners>
      </source>
      <source name="SignalR.ServiceBusMessageBus">
        <listeners>
          <add name="SignalR-Bus" />
        </listeners>
      </source>
      <source name="SignalR.ScaleoutMessageBus">
        <listeners>
          <add name="SignalR-Bus" />
        </listeners>
      </source>
    </sources>
    <switches>
      <add name="SignalRSwitch" value="Verbose" />
      <!-- Off, Critical, Error, Warning, Information, Verbose -->
    </switches>
    <sharedListeners>
      <add name="SignalR-Bus" 
          type="System.Diagnostics.TextWriterTraceListener" 
          initializeData="bus.log.txt" />
    </sharedListeners>
    <trace autoflush="true" />
  </system.diagnostics>
  . . .
</configuration>