共用方式為


SignalR 的向外延展簡介

作者 :Patrick Fletcher

警告

本檔不適用於最新版的 SignalR。 看看ASP.NET Core SignalR

本主題中使用的軟體版本

本主題的舊版

如需舊版 SignalR 的相關資訊,請參閱 SignalR 舊版

問題和批註

請留下您喜歡本教學課程的意見反應,以及我們可以在頁面底部的批註中改善的內容。 如果您有與教學課程不直接相關的問題,您可以將問題張貼至 ASP.NET SignalR 論壇StackOverflow.com

一般而言,有兩種方式可調整 Web 應用程式: 相應增加相應放大

  • 相應增加表示使用較大的伺服器 (或較大的 VM,) 具有更多 RAM、CPU 等。
  • 相應放大表示新增更多伺服器來處理負載。

相應增加的問題在於您快速達到機器大小的限制。 除此之外,您需要相應放大。不過,當您相應放大時,用戶端可以路由傳送至不同的伺服器。 連接到一部伺服器的用戶端將不會接收從另一部伺服器傳送的訊息。

此圖顯示從用戶端到Load Balancer到伺服器的箭號。

其中一個解決方案是使用稱為 背板的元件,在伺服器之間轉送訊息。 啟用背板後,每個應用程式實例都會將訊息傳送至幕後程式,而後板會將訊息轉送至其他應用程式實例。 (在電子裝置中,背板是一組平行連接器。藉由比喻,SignalR 背板會連接多部 server.)

此圖顯示從 Signal R App Server 到 Backplane 到 Signal R 應用程式伺服器到電腦的箭號。

SignalR 目前提供三個背板:

  • Azure 服務匯流排。 服務匯流排是一種傳訊基礎結構,可讓元件以鬆散結合的方式傳送訊息。
  • Redis。 Redis 是記憶體內部索引鍵/值存放區。 Redis 支援發佈/訂閱 (「pub/sub」) 模式來傳送訊息。
  • SQL Server。 SQL Server背板會將訊息寫入 SQL 資料表。 背板使用 Service Broker 進行有效率的傳訊。 不過,如果未啟用 Service Broker,它也會正常運作。

如果您在 Azure 上部署應用程式,請考慮使用 Azure Redis 快取使用 Redis備份表。 如果您要部署至自己的伺服器陣列,請考慮SQL Server或 Redis 備份表。

下列主題包含每個背板的逐步教學課程:

實作

在 SignalR 中,每個訊息都會透過訊息匯流排傳送。 訊息匯流排會實作 IMessageBus 介面,其提供發佈/訂閱抽象概念。 背板的運作方式是將預設 的 IMessageBus 取代為專為該背板設計的匯流排。 例如,Redis 的訊息匯流排是 RedisMessageBus,它會使用 Redis pub/sub 機制來傳送和接收訊息。

每個伺服器實例都會透過匯流排連線到背板。 當訊息傳送時,它會移至上架,而上架會將它傳送給每部伺服器。 當伺服器從上架取得訊息時,它會將訊息放在其本機快取中。 然後,伺服器會從其本機快取將訊息傳遞至用戶端。

針對每個用戶端連線,會使用資料指標來追蹤讀取訊息資料流程的用戶端進度。 (資料指標代表訊息資料流程中的位置。) 如果用戶端中斷連線,然後重新連線,它會要求匯流排輸入用戶端資料指標值之後抵達的任何訊息。 當連線使用 長時間輪詢時,會發生相同的情況。 長時間輪詢要求完成之後,用戶端會開啟新的連線,並要求在游標之後抵達的訊息。

即使用戶端在重新連線時路由傳送至不同的伺服器,資料指標機制仍可運作。 背板知道所有伺服器,而且用戶端所連線的伺服器並不重要。

限制

使用背板時,當用戶端直接與單一伺服器節點通訊時,訊息輸送量上限會低於此輸送量。 這是因為背板會將每個訊息轉送至每個節點,因此背板可能會成為瓶頸。 此限制是否為問題,取決於應用程式。 例如,以下是一些典型的 SignalR 案例:

  • 伺服器廣播 (例如庫存刻度) :備份板適用于此案例,因為伺服器會控制傳送訊息的速率。
  • 用戶端對用戶端 (例如聊天) :在此案例中,如果訊息數目隨著用戶端數目進行調整,幕後程式可能會是瓶頸;也就是說,如果訊息的速率隨著更多用戶端加入而按比例成長。
  • 高頻率即時 (例如即時遊戲) :此案例不建議使用上架。

啟用 SignalR 向外延展的追蹤

若要啟用背板的追蹤,請在根組 專案底下,將下列區段新增至web.config檔案:

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