Freigeben über


Einführung in die horizontale Skalierung in SignalR 1.x

von Patrick Fletcher

Warnung

Diese Dokumentation ist nicht für die neueste Version von SignalR vorgesehen. Sehen Sie sich ASP.NET Core SignalR an.

Im Allgemeinen gibt es zwei Möglichkeiten, eine Webanwendung zu skalieren: hochskalieren und horizontal hochskalieren.

  • Hochskalieren bedeutet, einen größeren Server (oder einen größeren virtuellen Computer) mit mehr RAM, CPUs usw. zu verwenden.
  • Horizontales Hochskalieren bedeutet, dass weitere Server hinzugefügt werden, um die Last zu bewältigen.

Das Problem beim Hochskalieren besteht darin, dass Sie schnell eine Größenbeschränkung für den Computer erreichen. Darüber hinaus müssen Sie horizontal hochskalieren. Wenn Sie jedoch horizontal hochskalieren, können Clients an verschiedene Server weitergeleitet werden. Ein Client, der mit einem Server verbunden ist, empfängt keine Nachrichten, die von einem anderen Server gesendet werden.

Screenshot des Problems, mit dem ein Client konfrontiert ist, wenn ein Server horizontal hochskaliert wird: Da er mit einem Server verbunden ist, empfängt er keine Nachrichten, die von einem anderen Server gesendet werden.

Eine Lösung besteht darin, Nachrichten zwischen Servern mithilfe einer Komponente, die als Backplane bezeichnet wird, weiterzuleiten. Wenn eine Backplane aktiviert ist, sendet jede Anwendung instance Nachrichten an die Backplane, und die Backplane leitet sie an die anderen Anwendungsinstanzen weiter. (In der Elektronik ist eine Backplane eine Gruppe von parallelen Verbindern. Analog dazu verbindet eine SignalR-Backplane mehrere Server.)

Screenshot der Lösung zum Weiterleiten von Nachrichten zwischen Servern mithilfe einer Komponente, die als Backplane bezeichnet wird.

SignalR bietet derzeit drei Backplanes:

  • Azure Service Bus Service Bus ist eine Messaginginfrastruktur, die es Komponenten ermöglicht, Nachrichten lose gekoppelt zu senden.
  • Redis. Redis ist ein Schlüssel-Wert-Speicher im Arbeitsspeicher. Redis unterstützt ein Publish/Subscribe-Muster ("pub/sub") für das Senden von Nachrichten.
  • SQL Server. Die SQL Server Backplane schreibt Nachrichten in SQL-Tabellen. Die Backplane verwendet Service Broker für effizientes Messaging. Dies funktioniert jedoch auch, wenn Service Broker nicht aktiviert ist.

Wenn Sie Ihre Anwendung in Azure bereitstellen, sollten Sie die Azure Service Bus Backplane verwenden. Wenn Sie die Bereitstellung in Ihrer eigenen Serverfarm durchführen, sollten Sie die backplanes SQL Server oder Redis in Betracht ziehen.

Die folgenden Themen enthalten Schritt-für-Schritt-Tutorials für jede Backplane:

Implementierung

In SignalR wird jede Nachricht über einen Nachrichtenbus gesendet. Ein Nachrichtenbus implementiert die IMessageBus-Schnittstelle , die eine Veröffentlichungs-/Abonnentenabstraktion bereitstellt. Die Backplanes funktionieren, indem der Standard-IMessageBus durch einen Bus ersetzt wird, der für diese Backplane entwickelt wurde. Der Nachrichtenbus für Redis ist beispielsweise RedisMessageBus und verwendet den Redis pub/sub-Mechanismus zum Senden und Empfangen von Nachrichten.

Jeder Server instance über den Bus eine Verbindung mit der Backplane herstellen. Wenn eine Nachricht gesendet wird, wird sie an die Backplane gesendet, und die Backplane sendet sie an jeden Server. Wenn ein Server eine Nachricht von der Backplane erhält, speichert er die Nachricht in seinen lokalen Cache. Der Server übermittelt dann Nachrichten aus dem lokalen Cache an Clients.

Für jede Clientverbindung wird der Fortschritt des Clients beim Lesen des Nachrichtendatenstroms mithilfe eines Cursors nachverfolgt. (Ein Cursor stellt eine Position im Nachrichtendatenstrom dar.) Wenn ein Client die Verbindung trennt und dann erneut verbindet, fragt er den Bus nach allen Nachrichten, die nach dem Cursorwert des Clients eingegangen sind. Dasselbe geschieht, wenn eine Verbindung lange Abrufe verwendet. Nach Abschluss einer langen Abfrageanforderung öffnet der Client eine neue Verbindung und fragt nach Nachrichten, die nach dem Cursor eingetroffen sind.

Der Cursormechanismus funktioniert auch, wenn ein Client bei der erneuten Verbindung an einen anderen Server weitergeleitet wird. Die Backplane kennt alle Server, und es spielt keine Rolle, mit welchem Server ein Client eine Verbindung herstellt.

Einschränkungen

Bei Verwendung einer Backplane ist der maximale Nachrichtendurchsatz niedriger als bei der direkten Kommunikation von Clients mit einem einzelnen Serverknoten. Das liegt daran, dass die Backplane jede Nachricht an jeden Knoten weiterleitet, sodass die Backplane zu einem Engpass werden kann. Ob diese Einschränkung ein Problem ist, hängt von der Anwendung ab. Hier sind beispielsweise einige typische SignalR-Szenarien:

  • Server-Broadcast (z. B. Aktienticker): Backplanes eignen sich gut für dieses Szenario, da der Server die Rate steuert, mit der Nachrichten gesendet werden.
  • Client-zu-Client (z. B. Chat): In diesem Szenario kann die Backplane ein Engpass sein, wenn die Anzahl der Nachrichten mit der Anzahl der Clients skaliert wird; Das heißt, wenn die Nachrichtenrate proportional zunimmt, wenn mehr Clients beitreten.
  • Hochfrequente Echtzeit (z. B. Echtzeitspiele): Eine Backplane wird für dieses Szenario nicht empfohlen.

Aktivieren der Ablaufverfolgung für signalr scaleout

Um die Ablaufverfolgung für die Backplanes zu aktivieren, fügen Sie der web.config-Datei unter dem Stammkonfigurationselement die folgenden Abschnitte hinzu:

<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>