SignalR 1.x 的向外延展簡介
作者: Patrick Fletcher
警告
本檔不適用於最新版的 SignalR。 請查看ASP.NET Core SignalR。
一般而言,有兩種方式可調整 Web 應用程式: 相應增加 和 相應放大。
- 相應增加表示使用較大的伺服器 (或較大的 VM) 具有更多 RAM、CPU 等。
- 相應放大表示新增更多伺服器來處理負載。
相應增加的問題在於您快速達到機器大小的限制。 除此之外,您必須相應放大。不過,當您相應放大時,用戶端可以路由傳送至不同的伺服器。 連線至一部伺服器的用戶端將不會接收從另一部伺服器傳送的訊息。
其中一個解決方案是使用稱為 背板的元件,在伺服器之間轉送訊息。 啟用後板後,每個應用程式實例都會將訊息傳送至背板,而後板會將訊息轉送至其他應用程式實例。 (在電子中,背板是一組平行連接器。藉由類比,SignalR 背板會連接多部 servers.)
SignalR 目前提供三個背板:
- Azure 服務匯流排。 服務匯流排是一種傳訊基礎結構,可讓元件以鬆散結合的方式傳送訊息。
- Redis。 Redis 是記憶體內部索引鍵/值存放區。 Redis 支援發佈/訂閱 (「pub/sub」) 模式來傳送訊息。
- SQL Server。 SQL Server背板會將訊息寫入 SQL 資料表。 背板會使用 Service Broker 進行有效率的傳訊。 不過,如果 Service Broker 未啟用,它也會運作。
如果您在 Azure 上部署應用程式,請考慮使用Azure 服務匯流排背板。 如果您要部署至自己的伺服器陣列,請考慮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>