次の方法で共有


SignalR のスケールアウト入門

作成者: Patrick Fletcher

警告

このドキュメントは、最新版の SignalR を対象としていません。 ASP.NET Core SignalR を参照してください。

このトピックで使用されるソフトウェアのバージョン

このトピックの以前のバージョン

SignalR の以前のバージョンの詳細については、「SignalR の以前のバージョン」を参照してください。

質問とコメント

このチュートリアルの感想、改善に関するフィードバックをページの下部にあるコメント欄にお寄せください。 チュートリアルに直接関連しない質問がある場合は、ASP.NET SignalR フォーラムまたは StackOverflow.com に投稿できます。

一般に、Web アプリケーションをスケーリングするには、"スケールアップ" と "スケールアウト" の 2 つの方法があります。

  • スケールアップとは、より多くの RAM、CPU などを備えたより大きなサーバー (またはより大きな VM) を使うことを意味します。
  • スケールアウトとは、負荷を処理するためにサーバーを追加することを意味します。

スケールアップの問題は、すぐにマシンのサイズの制限に達してしまうことです。 それを超えるには、スケールアウトする必要があります。ただし、スケールアウトすると、クライアントは異なるサーバーにルーティングされる可能性があります。 あるサーバーに接続されているクライアントは、別のサーバーから送信されたメッセージを受信しません。

Diagram that shows arrows going from Clients to Load Balancer to servers.

1 つの解決策は、"バックプレーン" というコンポーネントを使って、サーバー間でメッセージを転送することです。 バックプレーンが有効になっている場合、各アプリケーション・インスタンスはメッセージをバックプレーンに送信し、バックプレーンがメッセージを他のアプリケーション・インスタンスに転送します。 (エレクトロニクスでは、バックプレーンは並列コネクタのグループです。たとえば、SignalR バックプレーンでは複数のサーバーを接続します)

Diagram that shows arrows going from Signal R App server to Backplane to Signal R App server to computers.

SignalR には、現在、次の 3 つのバックプレーンが用意されています。

  • Azure Service Bus。 Service Bus は、コンポーネントが疎結合の方法でメッセージを送信できるようにするメッセージング インフラストラクチャです。
  • Redis。 Redis は、メモリ内のキー値ストアです。 Redis では、メッセージを送信するためのパブリッシュ/サブスクライブ ("pub/sub") パターンがサポートされています。
  • SQL Server。 SQL Server バックプレーンは、SQL テーブルにメッセージを書き込みます。 このバックプレーンは Service Broker を使用して効率的なメッセージングを行います。 ただし、Service Broker が有効になっていない場合にも機能します。

Azure にアプリケーションをデプロイする場合は、Azure Redis Cache を使う Redis バックプレーンの使用を検討してください。 独自のサーバー ファームにデプロイする場合は、SQL Server または Redis バックプレーンを検討してください。

次のトピックには、各バックプレーンの段階的なチュートリアルが含まれています。

実装

SignalR では、すべてのメッセージがメッセージ バスを通じて送信されます。 メッセージ バスは、パブリッシュ/サブスクライブの抽象化を提供する IMessageBus インターフェイスを実装します。 バックプレーンは、デフォルトの IMessageBus をそのバックプレーン用に設計されたバスに置き換えることで機能します。 たとえば、Redis のメッセージ バスは RedisMessageBus で、Redis pub/sub メカニズムを使ってメッセージを送受信します。

各サーバー インスタンスは、バスを介してバックプレーンに接続します。 メッセージが送信されると、それはバックプレーンに送られ、バックプレーンはそれをすべてのサーバーに送信します。 サーバーはバックプレーンからメッセージを受信すると、そのメッセージをローカル キャッシュに保持します。 その後、サーバーはローカル キャッシュからクライアントにメッセージを配信します。

クライアント接続ごとに、メッセージ ストリームの読み取りにおけるクライアントの進行状況が、カーソルを使って追跡されます (カーソルはメッセージ ストリーム内の位置を表します)。クライアントが切断してから再接続すると、クライアントのカーソル値の後に到着したメッセージをバスに要求します。 接続で長いポーリングを使う場合も同じことが発生します。 長いポーリング要求が完了すると、クライアントは新しい接続を開き、カーソルの後に到着したメッセージを要求します。

カーソル メカニズムは、再接続時にクライアントが別のサーバーにルーティングされた場合でも機能します。 バックプレーンはすべてのサーバーを認識しており、クライアントがどのサーバーに接続するかは関係ありません。

制限事項

バックプレーンを使うと、最大メッセージ スループットは、クライアントが単一サーバー ノードと直接通信する場合よりも低くなります。 これは、バックプレーンがすべてのメッセージをすべてのノードに転送するため、バックプレーンがボトルネックになる可能性があるためです。 この制限が問題になるかどうかはアプリケーションによって異なります。 たとえば、一般的な SignalR シナリオをいくつか次に示します。

  • サーバー ブロードキャスト (ストック ティッカーなど): サーバーがメッセージの送信速度を制御するため、このシナリオではバックプレーンが適切に機能します。
  • クライアント間 (チャットなど): このシナリオでは、メッセージの数がクライアントの数に応じてスケーリングする場合、つまり、より多くのクライアントが参加するにつれてメッセージのレートが比例して増加する場合、バックプレーンがボトルネックになる可能性があります。
  • 高頻度リアルタイム (リアルタイム ゲームなど): このシナリオでは、バックプレーンは推奨されません。

SignalR スケールアウトのトレースの有効化

バックプレーンのトレースを有効にするには、web.config ファイルのルートの configuration 要素の下に次のセクションを追加します。

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