Partilhar via


Dimensione o serviço SignalR com várias instâncias

O SDK do Serviço SignalR suporta vários pontos de extremidade para instâncias do Serviço SignalR. Você pode usar esse recurso para dimensionar as conexões simultâneas ou usá-lo para mensagens entre regiões.

Importante

As cadeias de conexão brutas aparecem neste artigo apenas para fins de demonstração.

Uma cadeia de conexão inclui as informações de autorização necessárias para seu aplicativo acessar o serviço Azure Web PubSub. A chave de acesso dentro da cadeia de conexão é semelhante a uma senha de root para o seu serviço. Em ambientes de produção, proteja sempre as suas chaves de acesso. Use o Azure Key Vault para gerenciar e girar suas chaves com segurança e proteger sua cadeia de conexão usando a ID do Microsoft Entra e autorizar o acesso com a ID do Microsoft Entra.

Evite distribuir chaves de acesso para outros usuários, codificá-las ou salvá-las em qualquer lugar em texto simples acessível a outras pessoas. Rode as chaves se acreditar que podem ter sido comprometidas.

Para ASP.NET Core

Adicionar vários pontos de extremidade a partir da configuração

As cadeias de conexão brutas aparecem neste artigo apenas para fins de demonstração. Em ambientes de produção, proteja sempre as suas chaves de acesso. Use o Azure Key Vault para gerenciar e girar suas chaves com segurança e proteger sua cadeia de conexão usando a ID do Microsoft Entra e autorizar o acesso com a ID do Microsoft Entra.

Configure com chave Azure:SignalR:ConnectionString ou Azure:SignalR:ConnectionString: para a cadeia de conexão do Serviço SignalR.

Se a chave começar com Azure:SignalR:ConnectionString:, ela deve estar no formato Azure:SignalR:ConnectionString:{Name}:{EndpointType}, onde Name e EndpointType são propriedades do objeto, e são acessíveis a ServiceEndpoint partir do código.

Você pode adicionar várias cadeias de conexão de instância usando os seguintes dotnet comandos:

dotnet user-secrets set Azure:SignalR:ConnectionString:east-region-a <ConnectionString1>
dotnet user-secrets set Azure:SignalR:ConnectionString:east-region-b:primary <ConnectionString2>
dotnet user-secrets set Azure:SignalR:ConnectionString:backup:secondary <ConnectionString3>

Adicionar vários pontos de extremidade do código

Uma ServiceEndpoint classe descreve as propriedades de um ponto de extremidade do Serviço Azure SignalR. Você pode configurar vários pontos de extremidade de instância ao usar o SDK do Serviço Azure SignalR por meio de:

services.AddSignalR()
        .AddAzureSignalR(options =>
        {
            options.Endpoints = new ServiceEndpoint[]
            {
                // Note: this is just a demonstration of how to set options.Endpoints
                // Having ConnectionStrings explicitly set inside the code is not encouraged
                // You can fetch it from a safe place such as Azure KeyVault
                new ServiceEndpoint("<ConnectionString0>"),
                new ServiceEndpoint("<ConnectionString1>", type: EndpointType.Primary, name: "east-region-a"),
                new ServiceEndpoint("<ConnectionString2>", type: EndpointType.Primary, name: "east-region-b"),
                new ServiceEndpoint("<ConnectionString3>", type: EndpointType.Secondary, name: "backup"),
            };
        });

Personalizar roteador de ponto final

Por padrão, o SDK usa o DefaultEndpointRouter para pegar pontos de extremidade.

Comportamento predefinido

  1. Roteamento de solicitação do cliente:

    Quando cliente /negotiate com o servidor de aplicativo. Por padrão, o SDK seleciona aleatoriamente um ponto de extremidade do conjunto de pontos de extremidade de serviço disponíveis.

  2. Roteamento de mensagens do servidor:

    Ao enviar uma mensagem para uma conexão específica e a conexão de destino é roteada para o servidor atual, a mensagem vai diretamente para esse ponto de extremidade conectado. Caso contrário, as mensagens serão transmitidas para cada ponto de extremidade do Azure SignalR.

Personalizar algoritmo de roteamento

Você pode criar seu próprio roteador quando tiver conhecimento especial para identificar para quais pontos finais as mensagens devem ir.

O exemplo a seguir define um roteador personalizado que roteia mensagens com um grupo começando com east- o ponto de extremidade chamado east:

private class CustomRouter : EndpointRouterDecorator
{
    public override IEnumerable<ServiceEndpoint> GetEndpointsForGroup(string groupName, IEnumerable<ServiceEndpoint> endpoints)
    {
        // Override the group broadcast behavior, if the group name starts with "east-", only send messages to endpoints inside east
        if (groupName.StartsWith("east-"))
        {
            return endpoints.Where(e => e.Name.StartsWith("east-"));
        }

        return base.GetEndpointsForGroup(groupName, endpoints);
    }
}

O exemplo a seguir substitui o comportamento de negociação padrão e seleciona o ponto de extremidade dependendo do local do servidor de aplicativo.

private class CustomRouter : EndpointRouterDecorator
{    public override ServiceEndpoint GetNegotiateEndpoint(HttpContext context, IEnumerable<ServiceEndpoint> endpoints)
    {
          // Sample code showing how to choose endpoints based on the incoming request endpoint query
          var endpointName = context.Request.Query["endpoint"].FirstOrDefault() ?? "";
          // Select from the available endpoints, don't construct a new ServiceEndpoint object here
          return endpoints.FirstOrDefault(s => s.Name == endpointName && s.Online) // Get the endpoint with name matching the incoming request
               ?? base.GetNegotiateEndpoint(context, endpoints); // Or fallback to the default behavior to randomly select one from primary endpoints, or fallback to secondary when no primary ones are online
    }
}

Não se esqueça de registrar o roteador no contêiner DI usando:

services.AddSingleton(typeof(IEndpointRouter), typeof(CustomRouter));
services.AddSignalR()
        .AddAzureSignalR(
            options =>
            {
                options.Endpoints = new ServiceEndpoint[]
                {
                    new ServiceEndpoint(name: "east", connectionString: "<connectionString1>"),
                    new ServiceEndpoint(name: "west", connectionString: "<connectionString2>"),
                    new ServiceEndpoint("<connectionString3>")
                };
            });

ServiceOptions.Endpoints também suporta hot-reload. O código de exemplo abaixo mostra como carregar cadeias de conexão de uma seção de configuração e URL pública exposta por proxies reversos de outra, e desde que a configuração suporte hot-reload, os pontos de extremidade podem ser atualizados imediatamente.

services.Configure<ServiceOptions>(o =>
{
        o.Endpoints = [
            new ServiceEndpoint(Configuration["ConnectionStrings:AzureSignalR:East"], name: "east")
            {
                ClientEndpoint = new Uri(Configuration.GetValue<string>("PublicClientEndpoints:East"))
            },
            new ServiceEndpoint(Configuration["ConnectionStrings:AzureSignalR:West"], name: "west")
            {
                ClientEndpoint = new Uri(Configuration.GetValue<string>("PublicClientEndpoints:West"))
            },
        ];
});

Para ASP.NET

Adicionar vários pontos de extremidade a partir da configuração

Configuração com chave Azure:SignalR:ConnectionString ou Azure:SignalR:ConnectionString: para cadeia de conexão do Serviço SignalR.

Se a chave começar com Azure:SignalR:ConnectionString:, ela deve estar no formato Azure:SignalR:ConnectionString:{Name}:{EndpointType}, onde Name e EndpointType são propriedades do objeto, e são acessíveis a ServiceEndpoint partir do código.

Você pode adicionar várias cadeias de conexão de instância a web.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <add name="Azure:SignalR:ConnectionString" connectionString="<ConnectionString1>"/>
    <add name="Azure:SignalR:ConnectionString:en-us" connectionString="<ConnectionString2>"/>
    <add name="Azure:SignalR:ConnectionString:zh-cn:secondary" connectionString="<ConnectionString3>"/>
    <add name="Azure:SignalR:ConnectionString:Backup:secondary" connectionString="<ConnectionString4>"/>
  </connectionStrings>
  ...
</configuration>

Adicionar vários pontos de extremidade do código

Uma ServiceEndpoint classe descreve as propriedades de um ponto de extremidade do Serviço Azure SignalR. Você pode configurar vários pontos de extremidade de instância ao usar o SDK do Serviço Azure SignalR por meio de:

app.MapAzureSignalR(
    this.GetType().FullName,
    options => {
            options.Endpoints = new ServiceEndpoint[]
            {
                // Note: this is just a demonstration of how to set options. Endpoints
                // Having ConnectionStrings explicitly set inside the code is not encouraged.
                // You can fetch it from a safe place such as Azure KeyVault
                new ServiceEndpoint("<ConnectionString1>"),
                new ServiceEndpoint("<ConnectionString2>"),
                new ServiceEndpoint("<ConnectionString3>"),
            }
        });

Personalizar um router

A única diferença entre ASP.NET SignalR e ASP.NET Core SignalR é o tipo de contexto http para GetNegotiateEndpoint. Para ASP.NET SignalR, é do tipo IOwinContext .

O código a seguir é um exemplo de negociação personalizada para ASP.NET SignalR:

private class CustomRouter : EndpointRouterDecorator
{
    public override ServiceEndpoint GetNegotiateEndpoint(IOwinContext context, IEnumerable<ServiceEndpoint> endpoints)
    {
        // Sample code showing how to choose endpoints based on the incoming request endpoint query
        var endpointName = context.Request.Query["endpoint"] ?? "";
        // Select from the available endpoints, don't construct a new ServiceEndpoint object here
        return endpoints.FirstOrDefault(s => s.Name == endpointName && s.Online) // Get the endpoint with name matching the incoming request
               ?? base.GetNegotiateEndpoint(context, endpoints); // Or fallback to the default behavior to randomly select one from primary endpoints, or fallback to secondary when no primary ones are online
    }
}

Não se esqueça de registrar o roteador no contêiner DI usando:

var hub = new HubConfiguration();
var router = new CustomRouter();
hub.Resolver.Register(typeof(IEndpointRouter), () => router);
app.MapAzureSignalR(GetType().FullName, hub, options => {
    options.Endpoints = new ServiceEndpoint[]
                {
                    new ServiceEndpoint(name: "east", connectionString: "<connectionString1>"),
                    new ServiceEndpoint(name: "west", connectionString: "<connectionString2>"),
                    new ServiceEndpoint("<connectionString3>")
                };
});

Métricas do ponto de extremidade do serviço

Para habilitar um roteador avançado, o SDK do servidor SignalR fornece várias métricas para ajudar o servidor a tomar decisões inteligentes. As propriedades estão em ServiceEndpoint.EndpointMetrics.

Nome da Métrica Description
ClientConnectionCount Contagem total de conexões de cliente simultâneas em todos os hubs para o ponto de extremidade do serviço
ServerConnectionCount Contagem total de conexões de servidor simultâneas em todos os hubs para o ponto de extremidade do serviço
ConnectionCapacity Cota total de conexão para o ponto de extremidade de serviço, incluindo conexões de cliente e servidor

O código a seguir é um exemplo de personalização de um roteador de acordo com .ClientConnectionCount

private class CustomRouter : EndpointRouterDecorator
{
    public override ServiceEndpoint GetNegotiateEndpoint(HttpContext context, IEnumerable<ServiceEndpoint> endpoints)
    {
        return endpoints.OrderBy(x => x.EndpointMetrics.ClientConnectionCount).FirstOrDefault(x => x.Online) // Get the available endpoint with minimal clients load
               ?? base.GetNegotiateEndpoint(context, endpoints); // Or fallback to the default behavior to randomly select one from primary endpoints, or fallback to secondary when no primary ones are online
    }
}

ServiceEndpoints de escala dinâmica

A partir da versão 1.5.0 do SDK, estamos habilitando primeiro ServiceEndpoints de escala dinâmica para ASP.NET versão Core. Assim, você não precisa reiniciar o servidor de aplicativos quando precisar adicionar/remover um ServiceEndpoint. Como o ASP.NET Core está suportando uma configuração padrão como appsettings.json reloadOnChange: truecom o , você não precisa alterar o código e ele é suportado pela natureza. E se você quiser adicionar alguma configuração personalizada e trabalhar com hot-reload, consulte Configuração no ASP.NET Core.

Nota

Considerando que o tempo de configuração da conexão entre servidor/serviço e cliente/serviço pode ser diferente, para garantir que nenhuma perda de mensagem durante o processo de escala, temos um período de preparação aguardando que as conexões do servidor estejam prontas antes de abrir o novo ServiceEndpoint para clientes. Normalmente, leva segundos para ser concluído e você poderá ver uma mensagem de log como Succeed in adding endpoint: '{endpoint}' a que indica que o processo foi concluído.

Em algumas situações esperadas, como problemas de rede entre regiões ou inconsistências de configuração em diferentes servidores de aplicativos, o período de preparo pode não terminar corretamente. Nesses casos, é sugerido reiniciar o servidor de aplicativos quando você achar que o processo de dimensionamento não está funcionando corretamente.

O período de tempo limite padrão para a escala é de 5 minutos e pode ser personalizado alterando o valor em ServiceOptions.ServiceScaleTimeout. Se você tiver muitos servidores de aplicativos, é sugerido estender o valor um pouco mais.

Nota

Atualmente, o recurso de vários pontos finais só é suportado no Persistent tipo de transporte.

Para extensões de funções SignalR

Configuração

Para habilitar várias instâncias do Serviço SignalR, você deve:

  1. Use Persistent o tipo de transporte.

    O tipo de transporte padrão é Transient modo. Você deve adicionar a seguinte entrada ao seu local.settings.json arquivo ou à configuração do aplicativo no Azure.

    {
        "AzureSignalRServiceTransportType":"Persistent"
    }
    

    Nota

    Ao alternar de modo para Persistent modo, pode haver alteração de comportamento de Transient serialização JSON, porque em Transient modo, Newtonsoft.Json biblioteca é usada para serializar argumentos de métodos de hub, no entanto, em modo, System.Text.Json biblioteca Persistent é usada como padrão. System.Text.Json tem algumas diferenças importantes no comportamento padrão com Newtonsoft.Jsono . Se quiser usar Newtonsoft.Json no Persistent modo, você pode adicionar um item de configuração: "Azure:SignalR:HubProtocol":"NewtonsoftJson" no local.settings.json arquivo ou Azure__SignalR__HubProtocol=NewtonsoftJson no portal do Azure.

  2. Configure várias entradas de pontos de extremidade do Serviço SignalR em sua configuração.

    Usamos um ServiceEndpoint objeto para representar uma instância do Serviço SignalR. Você pode definir um ponto de extremidade de serviço com seu <EndpointName> e <EndpointType> na chave de entrada e a cadeia de conexão no valor da entrada. As chaves estão no seguinte formato:

    Azure:SignalR:Endpoints:<EndpointName>:<EndpointType>
    

    <EndpointType> é opcional e o padrão é primary. Veja exemplos abaixo:

    {
        "Azure:SignalR:Endpoints:EastUs":"<ConnectionString>",
    
        "Azure:SignalR:Endpoints:EastUs2:Secondary":"<ConnectionString>",
    
        "Azure:SignalR:Endpoints:WestUs:Primary":"<ConnectionString>"
    }
    

    Nota

    • Ao configurar pontos de extremidade do Azure SignalR no Serviço de Aplicativo no portal do Azure, não se esqueça de substituir ":" por "__", o sublinhado duplo nas chaves. Para obter os motivos, consulte Variáveis de ambiente.

    • A cadeia de conexão configurada com a chave {ConnectionStringSetting} (padrão "AzureSignalRConnectionString") também é reconhecida como um ponto de extremidade de serviço primário com nome vazio. Mas esse estilo de configuração não é recomendado para vários pontos de extremidade.

Encaminhamento

Comportamento predefinido

Por padrão, a associação de funções usa o DefaultEndpointRouter para pegar pontos de extremidade.

  • Roteamento de cliente: selecione aleatoriamente um ponto de extremidade dos principais pontos de extremidade online . Se todos os pontos de extremidade primários estiverem offline, selecione aleatoriamente um ponto de extremidade online secundário. Se a seleção falhar novamente, a exceção será lançada.

  • Roteamento de mensagens do servidor: Todos os pontos de extremidade de serviço são retornados.

Personalização

Modelo em processo C#

Eis os passos:

  1. Implemente um roteador personalizado. Você pode aproveitar as informações fornecidas para tomar decisões de ServiceEndpoint roteamento. Veja o guia aqui: customize-route-algorithm. Observe que o gatilho Http é necessário na função de negociação quando você precisa HttpContext no método de negociação personalizado.

  2. Registre o roteador no contêiner DI.

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Azure.SignalR;
using Microsoft.Extensions.DependencyInjection;

[assembly: FunctionsStartup(typeof(SimpleChatV3.Startup))]
namespace SimpleChatV3
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddSingleton<IEndpointRouter, CustomizedRouter>();
        }
    }
}
Modelo de processo isolado

Para funções executadas em modelo de processo isolado, oferecemos suporte à especificação de pontos de extremidade de destino em cada solicitação. Você usará novos tipos de vinculação para obter informações de ponto final.

Encaminhamento de clientes

A SignalRConnectionInfo associação seleciona um ponto de extremidade de acordo com a regra de roteamento padrão. Se quiser personalizar a regra de roteamento, use SignalRNegotiation a vinculação em vez da SignalRConnectionInfo vinculação.

SignalRNegotiation As propriedades de configuração de vinculação são as mesmas que SignalRConnectionInfo. Aqui está um function.json exemplo de arquivo:

{
    "type": "signalRNegotiation",
    "name": "negotiationContext",
    "hubName": "<HubName>",
    "direction": "in"
}

Você também pode adicionar outros dados de vinculação, como userId, idToken e claimTypeList assim como SignalRConnectionInfo.

O objeto obtido da SignalRNegotiation vinculação está no seguinte formato:

{
    "endpoints": [
        {
            "endpointType": "Primary",
            "name": "<EndpointName>",
            "endpoint": "https://****.service.signalr.net",
            "online": true,
            "connectionInfo": {
                "url": "<client-access-url>",
                "accessToken": "<client-access-token>"
            }
        },
        {
            "...": "..."
        }
    ]
}

Aqui está um exemplo de uso de JavaScript de SignalRNegotiation vinculação:

module.exports = function (context, req, negotiationContext) {
    var userId = req.query.userId;
    if (userId.startsWith("east-")) {
        //return the first endpoint whose name starts with "east-" and status is online.
        context.res.body = negotiationContext.endpoints.find(endpoint => endpoint.name.startsWith("east-") && endpoint.online).connectionInfo;
    }
    else {
        //return the first online endpoint
        context.res.body = negotiationContext.endpoints.filter(endpoint => endpoint.online)[0].connectionInfo;
    }
}
Roteamento de mensagens

O roteamento de mensagens ou ações precisa de dois tipos de vinculação para cooperar. Em geral, em primeiro lugar, você precisa de um novo tipo SignalREndpoints de vinculação de entrada para obter todas as informações de ponto final disponíveis. Em seguida, você filtra os pontos de extremidade e obtém uma matriz contendo todos os pontos de extremidade para os quais deseja enviar. Por fim, você especifica os pontos de extremidade de destino na SignalR associação de saída.

Aqui estão as SignalREndpoints propriedades de configuração de vinculação no functions.json arquivo:

{
      "type": "signalREndpoints",
      "direction": "in",
      "name": "endpoints",
      "hubName": "<HubName>"
}

O objeto do SignalREndpoints qual você obtém é uma matriz de pontos de extremidade, cada um dos quais é representado como um objeto JSON com o seguinte esquema:

{
    "endpointType": "<EndpointType>",
    "name": "<EndpointName>",
    "endpoint": "https://****.service.signalr.net",
    "online": true
}

Depois de obter a matriz de ponto de extremidade de destino, adicione uma endpoints propriedade ao objeto de vinculação de saída. Este é um exemplo de JavaScript:

module.exports = function (context, req, endpoints) {
    var targetEndpoints = endpoints.filter(endpoint => endpoint.name.startsWith("east-"));
    context.bindings.signalRMessages = [{
        "target": "chat",
        "arguments": ["hello-world"],
        "endpoints": targetEndpoints,
    }];
    context.done();
}

Para SDK de gerenciamento

Adicionar vários pontos de extremidade a partir da configuração

Configure com chave Azure:SignalR:Endpoints para a cadeia de conexão do Serviço SignalR. A chave deve estar no formato Azure:SignalR:Endpoints:{Name}:{EndpointType}, onde Name e EndpointType são propriedades do objeto, e são acessíveis a ServiceEndpoint partir do código.

Você pode adicionar várias cadeias de conexão de instância usando os seguintes dotnet comandos:

dotnet user-secrets set Azure:SignalR:Endpoints:east-region-a <ConnectionString1>
dotnet user-secrets set Azure:SignalR:Endpoints:east-region-b:primary <ConnectionString2>
dotnet user-secrets set Azure:SignalR:Endpoints:backup:secondary <ConnectionString3>

Adicionar vários pontos de extremidade do código

Uma ServiceEndpoint classe descreve as propriedades de um ponto de extremidade do Serviço Azure SignalR. Você pode configurar vários pontos de extremidade de instância ao usar o SDK de Gerenciamento do Azure SignalR por meio de:

var serviceManager = new ServiceManagerBuilder()
                    .WithOptions(option =>
                    {
                        options.Endpoints = new ServiceEndpoint[]
                        {
                            // Note: this is just a demonstration of how to set options.Endpoints
                            // Having ConnectionStrings explicitly set inside the code is not encouraged
                            // You can fetch it from a safe place such as Azure KeyVault
                            new ServiceEndpoint("<ConnectionString0>"),
                            new ServiceEndpoint("<ConnectionString1>", type: EndpointType.Primary, name: "east-region-a"),
                            new ServiceEndpoint("<ConnectionString2>", type: EndpointType.Primary, name: "east-region-b"),
                            new ServiceEndpoint("<ConnectionString3>", type: EndpointType.Secondary, name: "backup"),
                        };
                    })
                    .BuildServiceManager();

Personalizar roteador de ponto final

Por padrão, o SDK usa o DefaultEndpointRouter para pegar pontos de extremidade.

Comportamento predefinido

  • Roteamento de solicitação do cliente:

    Quando cliente /negotiate com o servidor de aplicativo. Por padrão, o SDK seleciona aleatoriamente um ponto de extremidade do conjunto de pontos de extremidade de serviço disponíveis.

  • Roteamento de mensagens do servidor:

    Ao enviar uma mensagem para uma conexão específica e a conexão de destino é roteada para o servidor atual, a mensagem vai diretamente para esse ponto de extremidade conectado. Caso contrário, as mensagens serão transmitidas para cada ponto de extremidade do Azure SignalR.

Personalizar algoritmo de roteamento

Você pode criar seu próprio roteador quando tiver conhecimento especial para identificar para quais pontos finais as mensagens devem ir.

O exemplo a seguir define um roteador personalizado que roteia mensagens com um grupo começando com east- o ponto de extremidade chamado east:

private class CustomRouter : EndpointRouterDecorator
{
    public override IEnumerable<ServiceEndpoint> GetEndpointsForGroup(string groupName, IEnumerable<ServiceEndpoint> endpoints)
    {
        // Override the group broadcast behavior, if the group name starts with "east-", only send messages to endpoints inside east
        if (groupName.StartsWith("east-"))
        {
            return endpoints.Where(e => e.Name.StartsWith("east-"));
        }

        return base.GetEndpointsForGroup(groupName, endpoints);
    }
}

O exemplo a seguir substitui o comportamento de negociação padrão e seleciona o ponto de extremidade dependendo do local do servidor de aplicativo.

private class CustomRouter : EndpointRouterDecorator
{    public override ServiceEndpoint GetNegotiateEndpoint(HttpContext context, IEnumerable<ServiceEndpoint> endpoints)
    {
        // Override the negotiate behavior to get the endpoint from query string
        var endpointName = context.Request.Query["endpoint"];
        if (endpointName.Count == 0)
        {
            context.Response.StatusCode = 400;
            var response = Encoding.UTF8.GetBytes("Invalid request");
            context.Response.Body.Write(response, 0, response.Length);
            return null;
        }

        return endpoints.FirstOrDefault(s => s.Name == endpointName && s.Online) // Get the endpoint with name matching the incoming request
               ?? base.GetNegotiateEndpoint(context, endpoints); // Or fallback to the default behavior to randomly select one from primary endpoints, or fallback to secondary when no primary ones are online
    }
}

Não se esqueça de registrar o roteador no contêiner DI usando:

var serviceManager = new ServiceManagerBuilder()
                    .WithOptions(option =>
                    {
                        options.Endpoints = new ServiceEndpoint[]
                        {
                            // Note: this is just a demonstration of how to set options.Endpoints
                            // Having ConnectionStrings explicitly set inside the code is not encouraged
                            // You can fetch it from a safe place such as Azure KeyVault
                            new ServiceEndpoint("<ConnectionString0>"),
                            new ServiceEndpoint("<ConnectionString1>", type: EndpointType.Primary, name: "east-region-a"),
                            new ServiceEndpoint("<ConnectionString2>", type: EndpointType.Primary, name: "east-region-b"),
                            new ServiceEndpoint("<ConnectionString3>", type: EndpointType.Secondary, name: "backup"),
                        };
                    })
                    .WithRouter(new CustomRouter())
                    .BuildServiceManager();

Configuração em cenários entre regiões

O ServiceEndpoint objeto tem uma EndpointType propriedade com valor primary ou secondary.

Os pontos de extremidade primários são pontos de extremidade preferenciais para receber tráfego de cliente porque eles têm conexões de rede mais confiáveis. Os pontos de extremidade secundários têm conexões de rede menos confiáveis e são usados apenas para tráfego de servidor para cliente. Por exemplo, pontos de extremidade secundários são usados para transmitir mensagens em vez de tráfego de cliente para servidor.

Em casos entre regiões, a rede pode ser instável. Para um servidor de aplicativos localizado no Leste dos EUA, o ponto de extremidade do Serviço SignalR localizado na mesma região Leste dos EUA é primary e pontos de extremidade em outras regiões marcados como secondary. Nessa configuração, os pontos de extremidade de serviço em outras regiões podem receber mensagens desse servidor de aplicativos do Leste dos EUA, mas nenhum cliente entre regiões é roteado para esse servidor de aplicativo. O diagrama a seguir mostra a arquitetura:

Cross-Geo Infra

Quando um cliente tenta /negotiate com o servidor de aplicativos com um roteador padrão, o SDK seleciona aleatoriamente um ponto de extremidade do conjunto de pontos de extremidade disponíveis primary . Quando o ponto de extremidade primário não está disponível, o SDK seleciona aleatoriamente entre todos os pontos de extremidade disponíveissecondary. O ponto de extremidade é marcado como disponível quando a conexão entre o servidor e o ponto de extremidade de serviço está ativa.

Em um cenário entre regiões, quando um cliente tenta /negotiate com o servidor de aplicativos hospedado no Leste dos EUA, por padrão, ele sempre retorna o primary ponto de extremidade localizado na mesma região. Quando todos os pontos de extremidade do Leste dos EUA não estão disponíveis, o roteador redireciona o cliente para pontos de extremidade em outras regiões. A seção de failover a seguir descreve o cenário em detalhes.

Negociação Normal

Ativação pós-falha

Quando nenhum primary ponto de extremidade está disponível, o cliente escolhe entre os /negotiate pontos de extremidade disponíveis secondary . Esse mecanismo de failover requer que cada ponto de extremidade sirva como um primary ponto de extremidade para pelo menos um servidor de aplicativo.

Diagrama mostrando o processo do mecanismo de failover.

Próximos passos

Você pode usar vários pontos de extremidade em cenários de alta disponibilidade e recuperação de desastres.