Azure SignalR Service 中的復原和災害復原
復原和災害復原是在線系統的常見需求。 Azure SignalR Service 已提供 99.9% 的可用性,但仍是區域服務。 當發生全區域中斷時,您的服務實例不會故障轉移至另一個區域,因為它一律在一個區域中執行。
針對區域災害復原,我們建議使用下列兩種方法:
- 啟用異地復寫 (簡單方式)。 此功能會自動為您處理區域故障轉移。 啟用時,只有一個 Azure SignalR 實例,而且不會導入任何程式代碼變更。 如需詳細數據,請查看 異地複寫 。
- 在服務 SDK 中使用多個端點。 我們的服務 SDK 支援多個 SignalR 服務實例,並在部分實例無法使用時自動切換至其他實例。 有了這項功能,您就可以在發生災害時復原,但您必須自行設定正確的系統拓撲。 您將瞭解如何在本文件中執行此 動作。
SignalR 服務的高可用性架構
若要確保 SignalR 服務的跨區域復原能力,您必須在不同的區域中設定多個服務實例。 因此,當某個區域關閉時,其他區域可以做為備份。 當應用程式伺服器連線到多個服務實例時,主要和次要角色有兩個。 主要是負責接收在線流量的實例,而次要實例則作為可完全運作的後援實例。 在我們的 SDK 實作中,交涉只會傳回主要端點,因此用戶端只會在正常情況下連線到主要端點。 但是,當主要實例關閉時,交涉會傳回次要端點,讓用戶端仍然可以建立連線。 主要實例和應用程式伺服器是透過一般伺服器連線,但次要實例和應用程式伺服器會透過稱為弱式連線的特殊連線類型進行連線。 弱式連線的一個區別特性是,由於次要實例在另一個區域中的位置,它無法接受用戶端連線路由。 將用戶端路由至另一個區域不是最佳選擇(增加延遲)。
線上到多個應用程式伺服器時,一個服務實例可以有不同的角色。 跨區域案例的一個典型設定是有兩個以上的 SignalR 服務實例和應用程式伺服器。 在每個配對應用程式伺服器和 SignalR 服務內都位於相同的區域,而 SignalR 服務會以主要角色連線到應用程式伺服器。 每個配對的應用程式伺服器和 SignalR 服務之間也會連線,但 SignalR 會在連線到另一個區域中的伺服器時成為次要伺服器。
透過此拓撲,當所有應用程式伺服器和 SignalR 服務實例互連時,一部伺服器的訊息仍可傳遞至所有用戶端。 但是當用戶端連線時,它會路由傳送至相同區域中的應用程式伺服器,以達到最佳的網路等待時間。
下圖說明這類拓撲:
設定多個 SignalR 服務實例
應用程式伺服器和 Azure Functions 都支援多個 SignalR 服務實例。
在每個區域中建立 SignalR 服務和應用程式伺服器/Azure Functions 之後,您就可以設定應用程式伺服器/Azure Functions 來連線到所有 SignalR 服務實例。
在應用程式伺服器上設定
有兩種方式可以執行:
透過組態
您應該已經知道如何在名為 Azure:SignalR:ConnectionString
的組態專案中,透過環境變數/應用程式設定/web.cofig 設定 SignalR 服務 連接字串。
如果您有多個端點,您可以使用多個組態項目來設定它們,每個端點都以下列格式設定:
Azure:SignalR:ConnectionString:<name>:<role>
在 連線 ionString 中,<name>
是端點的名稱,而且<role>
是其角色(主要或次要)。
名稱是選擇性的,但如果您想要進一步自定義多個端點之間的路由行為,這會很有用。
透過程序代碼
如果您想要將 連接字串 儲存在別的地方,您也可以在程式代碼中讀取它們,並在呼叫 AddAzureSignalR()
時將其當做參數使用(在 ASP.NET Core 中)或 MapAzureSignalR()
(ASP.NET)。
以下是範例程式代碼:
ASP.NET Core:
services.AddSignalR()
.AddAzureSignalR(options => options.Endpoints = new ServiceEndpoint[]
{
new ServiceEndpoint("<connection_string1>", EndpointType.Primary, "region1"),
new ServiceEndpoint("<connection_string2>", EndpointType.Secondary, "region2"),
});
ASP.NET:
app.MapAzureSignalR(GetType().FullName, hub, options => options.Endpoints = new ServiceEndpoint[]
{
new ServiceEndpoint("<connection_string1>", EndpointType.Primary, "region1"),
new ServiceEndpoint("<connection_string2>", EndpointType.Secondary, "region2"),
};
您可以設定多個主要或次要實例。 如果有多個主要和/或次要實例,交涉會依下列順序傳回端點:
- 如果至少有一個主要實例在在線,則傳回隨機的主要在線實例。
- 如果所有主要實例都關閉,則傳回隨機次要在線實例。
在 Azure Functions 上設定
請參閱 這篇文章。
故障轉移順序和最佳做法
現在您已設定正確的系統拓撲。 每當一個 SignalR 服務實例關閉時,在線流量就會路由傳送至其他實例。 以下是當主要實例關閉時會發生什麼情況(並在一段時間后復原):
- 主要服務實例已關閉,此實例上的所有伺服器連線都會卸除。
- 連線至此實例的所有伺服器都會將其標示為離線,交涉會停止傳回此端點,並開始傳回次要端點。
- 此實例上的所有用戶端連線也會關閉,客戶端接著會重新連線。 由於應用程式伺服器現在會傳回次要端點,用戶端會連線到次要實例。
- 現在次要實例會採用所有在線流量。 從伺服器到用戶端的所有訊息仍可傳遞為次要連線到所有應用程式伺服器。 但客戶端對伺服器訊息只會路由傳送至相同區域中的應用程式伺服器。
- 在主要實例復原並重新上線之後,應用程式伺服器會重新建立與其連線,並將其標示為在線。 交涉現在會再次傳回主要端點,讓新的用戶端重新連線到主要端點。 但現有的用戶端不會卸除,而且在中斷連線之前仍會路由傳送至次要用戶端。
下圖說明如何在 SignalR 服務中完成故障轉移:
Fig.1 故障轉移前
Fig.2 故障轉移之後
Fig.3 主要復原后的短時間
一般情況下,只有主要應用程式伺服器和 SignalR 服務才會有在線流量(藍色)。 故障轉移之後,次要應用程式伺服器和 SignalR 服務也會變成作用中。 在主要 SignalR 服務重新上線之後,新的用戶端會連線到主要 SignalR。 但現有的用戶端仍會連線到次要用戶端,因此這兩個實例都有流量。 在所有現有的用戶端中斷連線之後,您的系統將會恢復正常狀態 (Fig.1)。
實作跨區域高可用性架構的主要模式有兩種:
- 第一個是讓一對應用程式伺服器和 SignalR 服務實例取得所有在線流量,並讓另一組作為備份(如圖 1 所示的主動/被動)。
- 另一個是有兩個(或更多)組的應用程式伺服器和 SignalR 服務實例,每個實例都參與在線流量,並作為其他配對的備份(稱為作用中/主動,類似於 Fig.3)。
SignalR 服務可以支援這兩種模式,主要差異在於您實作應用程式伺服器的方式。 如果應用程式伺服器是主動/被動,SignalR 服務也是主動/被動(因為主要應用程式伺服器只會傳回其主要 SignalR 服務實例)。 如果應用程式伺服器為主動/主動,SignalR 服務也是作用中/主動(因為所有應用程式伺服器都會傳回自己的主要 SignalR 實例,因此所有伺服器都可以取得流量)。
無論您選擇使用何種模式,都必須將每個 SignalR 服務實例連線到應用程式伺服器做為主要伺服器。
此外,由於 SignalR 連線的性質(這是很長的連線),用戶端在發生災害和故障轉移時遇到連線中斷。 您必須在客戶端處理這類案例,讓您的終端客戶能夠透明。 例如,在連接關閉之後重新連線機。
如何測試故障轉移
請遵循下列步驟來觸發故障轉移:
- 在入口網站中主要資源的 [網络] 索引標籤中, 停用 公用網路存取。 如果資源已啟用專用網,請使用 訪問控制規則 來拒絕所有流量。
- 重新啟動 主要資源。
下一步
在本文中,您已瞭解如何設定應用程式以達到 SignalR 服務的復原能力。 若要深入瞭解 SignalR 服務中的伺服器/用戶端連線和連線路由的詳細資訊,您可以閱讀 本文 以取得 SignalR 服務內部。
針對調整案例,例如一起使用多個實例的分區化來處理大量連線,請參閱 如何調整多個實例。
如需如何使用多個 SignalR 服務實例設定 Azure Functions 的詳細資訊,請閱讀 Azure Functions 中的多個 Azure SignalR 服務實例支援。