伺服器正常關機
當 Microsoft Azure SignalR Service 設定為預設模式,而由 Azure SignalR Service 充當 SignalR 用戶端與 SignalR 中樞伺服器之間的 Proxy 時,Azure SignalR Service 提供兩種模式來正常關閉 SignalR 中樞伺服器。
使用此功能的主要優點是避免客戶遇到意外的連線中斷。
相反地,您可以根據商務邏輯,等候用戶端連線自行關閉,或甚至將用戶端連線移轉至另一部伺服器,而不會遺失資料。
運作方式
一般而言,正常關機程序有四個階段:
將伺服器設定為離線
這表示不會再有用戶端連線路由至此伺服器。
觸發
OnShutdown
勾點您可以為您在伺服器中擁有的每個中樞註冊關機勾點。 在我們收到 Azure SignalR Service 的 FINACK 回應之後,即 Azure SignalR Service 中已將此伺服器設定為離線,將會依註冊順序立即呼叫勾點。
在這個階段,您可廣播訊息或執行一些清除作業,一旦執行所有關機勾點,我們就會繼續進行下一個階段。
等候所有用戶端連線完成,視您選擇的模式而定,可能是:
模式設定為 WaitForClientsToClose
Azure SignalR Service 會保留現有的用戶端。
您可能必須設計一種方式,例如將關閉訊息廣播給所有用戶端,然後讓用戶端決定何時關閉/重新連線本身。
請參閱 ChatSample 使用方式範例,其中我們在關機勾點中廣播 'exit' 訊息以觸發用戶端關閉。
模式設定為 MigrateClients
Azure SignalR Service 會嘗試將此伺服器上的用戶端連線重新路由至另一個有效的伺服器。
在此情況下,由於在
Context
中設定IConnectionMigrationFeature
(可用來識別是否正在移入或移出用戶端連線),將會分別在新伺服器和舊伺服器上觸發OnConnectedAsync
和OnDisconnectedAsync
。這項功能在具狀態情況下特別有用。傳遞目前的訊息之後會立即移轉用戶端連線,這表示下一個訊息會路由至新的伺服器。
停止伺服器連線
在關閉/移轉所有用戶端連線,或超過逾時 (預設 30 秒) 之後,
SignalR Server SDK 會進行此階段的關機程序,並關閉所有伺服器連線。
如果用戶端連線無法關閉/移轉,仍然會中斷。 例如,尚未完成適當的目標伺服器/目前的用戶端對伺服器訊息。
範例程式碼。
使用 AddAzureSignalR
新增下列選項:
services.AddSignalR().AddAzureSignalR(option =>
{
option.GracefulShutdown.Mode = GracefulShutdownMode.WaitForClientsClose;
// option.GracefulShutdown.Mode = GracefulShutdownMode.MigrateClients;
option.GracefulShutdown.Timeout = TimeSpan.FromSeconds(30);
option.GracefulShutdown.Add<Chat>(async (c) =>
{
await c.Clients.All.SendAsync("exit");
});
});
將正常關機模式設定為 MigrateClients
時,設定 OnConnected
和 OnDisconnected
。
我們引進了 "IConnectionMigrationFeature",以指出是否正在移入/移出連線。
public class Chat : Hub {
public override async Task OnConnectedAsync()
{
Console.WriteLine($"{Context.ConnectionId} connected.");
var feature = Context.Features.Get<IConnectionMigrationFeature>();
if (feature != null)
{
Console.WriteLine($"[{feature.MigrateTo}] {Context.ConnectionId} is migrated from {feature.MigrateFrom}.");
// Your business logic.
}
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception e)
{
Console.WriteLine($"{Context.ConnectionId} disconnected.");
var feature = Context.Features.Get<IConnectionMigrationFeature>();
if (feature != null)
{
Console.WriteLine($"[{feature.MigrateFrom}] {Context.ConnectionId} will be migrated to {feature.MigrateTo}.");
// Your business logic.
}
await base.OnDisconnectedAsync(e);
}
}