Desligamento normal do servidor

O serviço de SignalR do Microsoft Azure fornece dois modos para desligar um servidor de Hub do SignalR normalmente quando o serviço de SignalR do azure é configurado como Modo padrão que o serviço de SignalR do azure atua como um proxy entre os clientes do SignalR e o servidor do Hub do SignalR.

A principal vantagem de usar esse recurso é impedir que o cliente tenha quedas de conexão inesperadas.

Em vez disso, você poderia esperar que as conexões de cliente se fechem em relação à lógica de negócios ou até mesmo migrar a conexão do cliente para outro servidor sem perder dados.

Como ele funciona

Em geral, haverá quatro estágios em um processo de desligamento normal:

  1. Definir o servidor offline

    Isso significa que nenhuma conexão de cliente será roteada para esse servidor.

  2. Disparar OnShutdown ganchos

    Você pode registrar ganchos de desligamento para cada hub que você possui em seu servidor. Eles serão chamados em relação ao pedido registrado logo após recebermos uma resposta FINACK do nosso Serviço Azure SignalR, o que significa que esse servidor foi definido offline no Serviço Azure SignalR.

    Você pode transmitir mensagens ou fazer alguns trabalhos de limpeza neste estágio, uma vez que todos os ganchos de desligamento tenham sido executados, passaremos para o próximo estágio.

  3. Aguarde até que todas as conexões de cliente sejam concluídas, dependendo do modo escolhido, pode ser:

    Modo definido como WaitForClientsToClose

    O Serviço do Azure SignalR manterá os clientes existentes.

    Você pode ter que projetar uma maneira, como transmitir uma mensagem de fechamento para todos os clientes e, em seguida, deixar que seus clientes decidam quando fechar/se reconectar.

    Leia ChatSample para uso de exemplo, em que transmitimos uma mensagem 'exit' para disparar o fechamento do cliente no gancho de desligamento.

    Modo definido como MigrateClients

    O Serviço do Azure SignalR tentará redirecionar a conexão do cliente nesse servidor para outro servidor válido.

    Nesse cenário, e será acionado no novo servidor e OnDisconnectedAsync no servidor antigo, respectivamente, com um IConnectionMigrationFeature conjunto no Context, OnConnectedAsync que pode ser usado para identificar se a conexão do cliente estava sendo migrada para dentro ou para fora. Esse recurso pode ser útil especialmente para cenários com monitoração de estado.

    A conexão do cliente será migrada imediatamente depois que a mensagem atual tiver sido entregue, o que significa que a próxima mensagem será roteada para o novo servidor.

  4. Parar conexões de servidor

    Depois que todas as conexões de cliente tiverem sido fechadas/migradas ou o tempo limite (30s por padrão) tiver sido excedido,

    O SDK do SignalR Server prosseguirá com o processo de desligamento para esse estágio e fechará todas as conexões de servidor.

    As conexões de cliente ainda serão descartadas se não tiver ocorrido falha no fechamento/na migração. Por exemplo, nenhuma mensagem de servidor de destino/de cliente para servidor atual adequada foi concluída.

Códigos de exemplo.

Adicione as seguintes opções quando 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");
    });
});

configurar OnConnected e OnDisconnected ao definir o modo de desligamento normal como MigrateClients.

Introduzimos um "IConnectionMigrationFeature" para indicar se uma conexão estava sendo migrada para dentro/para fora.

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);
    }
}