次の方法で共有


複数のインスタンスがある SignalR Service のスケーリング

SignalR Service SDK では、SignalR Service インスタンスの複数のエンドポイントがサポートされています。 この機能を使用して同時接続をスケーリングすることや、リージョンをまたがるメッセージングにこれを使用することができます。

重要

この記事に示す生の接続文字列は、デモンストレーションのみを目的としています。

接続文字列には、アプリケーションが Azure Web PubSub サービスにアクセスするために必要な認可情報が含まれています。 接続文字列内のアクセス キーは、サービスのルート パスワードに似ています。 運用環境では、常にアクセス キーを保護してください。 Azure Key Vault を使用してキーの管理とローテーションを安全に行い、Microsoft Entra ID を使用して接続文字列をセキュリティで保護し、Microsoft Entra ID を使用してアクセスを認可します。

アクセス キーを他のユーザーに配布したり、ハードコーディングしたり、他のユーザーがアクセスできるプレーンテキストで保存したりしないでください。 キーが侵害された可能性があると思われる場合は、キーをローテーションしてください。

ASP.NET Core の場合

構成から複数のエンドポイントを追加する

この記事では、デモの目的でのみ、この生の接続文字列を表示しています。 運用環境では、常にアクセス キーを保護してください。 Azure Key Vault を使用してキーの管理とローテーションを安全に行い、Microsoft Entra ID を使用して接続文字列をセキュリティで保護し、Microsoft Entra ID を使用してアクセスを認可します。

SignalR Service 接続文字列のキー Azure:SignalR:ConnectionString または Azure:SignalR:ConnectionString: を使用して構成します。

キーが Azure:SignalR:ConnectionString: で開始する場合、Azure:SignalR:ConnectionString:{Name}:{EndpointType} の形式にする必要があります。ここで、NameEndpointType は、ServiceEndpoint オブジェクトのプロパティであり、コードからアクセス可能です。

次の dotnet コマンドを使用して、複数のインスタンス接続文字列を追加できます。

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>

コードから複数のエンドポイントを追加する

ServiceEndpoint クラスには、Azure SignalR Service エンドポイントのプロパティが示されています。 次のように、Azure SignalR Service SDK を使用して複数のインスタンス エンドポイントを構成できます。

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

エンドポイント ルーターをカスタマイズする

既定では、SDK では DefaultEndpointRouter を使用してエンドポイントを選択します。

既定の動作

  1. クライアント要求のルーティング:

    クライアントがアプリ サーバーを使用して /negotiate すると、 既定では、SDK は使用可能な一連のサービス エンドポイントから 1 つのエンドポイントをランダムに選択します。

  2. サーバー メッセージのルーティング:

    特定の接続にメッセージを送信すると、ターゲット接続は現在のサーバーにルーティングされ、メッセージは接続済みエンドポイントに直接送信されます。 それ以外の場合、メッセージはすべての Azure SignalR エンドポイントにブロードキャストされます。

ルーティング アルゴリズムをカスタマイズする

メッセージの送信先エンドポイントを特定する特別な知識を持っている場合は、独自のルーターを作成できます。

次の例では、east- で始まるグループのメッセージを 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);
    }
}

次の例では、既定のネゴシエート動作をオーバーライドし、アプリ サーバーの場所に応じてエンドポイントを選択します。

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

次のように、必ずルーターを DI コンテナーに登録してください。

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 は、ホット リロードもサポートしています。 以下のサンプル コードは、ある構成セクションから接続文字列を読み込み、別の構成セクションからリバース プロキシによって公開されるパブリック URL を読み込む方法を示しています。構成がホット リロードをサポートしている限り、エンドポイントはオンザフライで更新されます。

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"))
            },
        ];
});

ASP.NET の場合

構成から複数のエンドポイントを追加する

SignalR Service 接続文字列のキー Azure:SignalR:ConnectionString または Azure:SignalR:ConnectionString: を使用して構成します。

キーが Azure:SignalR:ConnectionString: で開始する場合、Azure:SignalR:ConnectionString:{Name}:{EndpointType} の形式にする必要があります。ここで、NameEndpointType は、ServiceEndpoint オブジェクトのプロパティであり、コードからアクセス可能です。

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>

コードから複数のエンドポイントを追加する

ServiceEndpoint クラスには、Azure SignalR Service エンドポイントのプロパティが示されています。 次のように、Azure SignalR Service SDK を使用して複数のインスタンス エンドポイントを構成できます。

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

ルーターをカスタマイズする

ASP.NET SignalR と ASP.NET Core SignalR の唯一の相違は、GetNegotiateEndpoint の http コンテキスト型です。 ASP.NET SignalR の場合は IOwinContext 型です。

次のコードは、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
    }
}

次のように、必ずルーターを DI コンテナーに登録してください。

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

サービス エンドポイントのメトリック

高度なルーターを有効にするために、SignalR サーバー SDK では、サーバーによるスマートな決定に役立つ複数のメトリックが提供されます。 プロパティは ServiceEndpoint.EndpointMetrics の下にあります。

メトリックの名前 説明
ClientConnectionCount サービス エンドポイントのすべてのハブにある同時クライアント接続の合計数
ServerConnectionCount サービス エンドポイントのすべてのハブにある同時サーバー接続の合計数
ConnectionCapacity クライアント接続とサーバー接続を含む、サービス エンドポイントの接続クォータの合計

次のコードは、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

SDK バージョン 1.5.0 から、最初に ASP.NET Core バージョンの動的スケール ServiceEndpoints を有効にしています。 そのため、ServiceEndpoint を追加または削除する必要があるときに、アプリ サーバーを再起動する必要はありません。 reloadOnChange: true を指定した appsettings.json のような既定の構成が ASP.NET Core でサポートされているため、コードを変更する必要がなく、本質的にサポートされています。 また、カスタマイズした構成を追加してホット リロードを使用する場合は、「ASP.NET Core の構成」を参照してください。

Note

サーバー/サービスとクライアント/サービスの間の接続設定の時間が異なる場合があることを考慮し、スケール プロセス中にメッセージが失われないようにするため、新しい ServiceEndpoint をクライアントに開く前にサーバー接続の準備が整うのを待つステージング期間があります。 通常、完了するまでに数秒かかり、プロセスが完了したことを示す Succeed in adding endpoint: '{endpoint}' のようなログ メッセージを確認できます。

リージョンをまたがるネットワークの問題や異なるアプリ サーバーでの構成の不一致など、予期される状況によっては、ステージング期間が正しく終了しない可能性があります。 このような場合、スケーリング プロセスが正しく動作していないことがわかったら、アプリ サーバーを再起動することをお勧めします。

スケールの既定のタイムアウト期間は 5 分で、ServiceOptions.ServiceScaleTimeout の値を変更してカスタマイズできます。 多数のアプリ サーバーがある場合は、もう少し値を拡張することをお勧めします。

Note

現在、マルチエンドポイント機能は、Persistent トランスポートの種類でのみサポートされています。

SignalR Functions 拡張機能の場合

構成

複数の SignalR Service インスタンスを有効にするには、次のことを行う必要があります。

  1. Persistent の転送の種類を使用します。

    既定のトランスポートの種類は Transient モードです。 次のエントリを local.settings.json ファイルまたは Azure のアプリケーション設定に追加する必要があります。

    {
        "AzureSignalRServiceTransportType":"Persistent"
    }
    

    Note

    Transient モードから Persistent モードに切り替えると、JSON シリアル化の動作が変わる可能性があります。これは、Transient モードでは、ハブ メソッドの引数のシリアル化に Newtonsoft.Json ライブラリが使用されますが、Persistent モードでは、System.Text.Json ライブラリが既定で使用されるためです。 System.Text.Json には、Newtonsoft.Json との既定の動作にいくつかの重要な違いがあります。 Persistent モードで Newtonsoft.Json を使用する場合は、構成項目 (local.settings.json ファイルでは "Azure:SignalR:HubProtocol":"NewtonsoftJson"、または Azure portal では Azure__SignalR__HubProtocol=NewtonsoftJson) を追加できます。

  2. 構成で複数の SignalR Service エンドポイント エントリを構成します。

    ServiceEndpoint オブジェクトを使用して SignalR Service インスタンスを表します。 エントリ キーに <EndpointName><EndpointType>、エントリ値に接続文字列を使用してサービス エンドポイントを定義できます。 キーの形式は次のとおりです。

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

    <EndpointType> は省略可能であり、既定値は primary です。 以下のサンプルを参照してください。

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

    Note

    • Azure portal の App Service で Azure SignalR エンドポイントを構成するときは、必ずキー内の ":""__" (二重アンダースコア) に置き換えます。 理由については、環境変数に関する記事を参照してください。

    • また、キー {ConnectionStringSetting} を使用して構成された接続文字列 (既定値は "AzureSignalRConnectionString") は、名前が空のプライマリ サービス エンドポイントとして認識されます。 ただし、この構成スタイルは複数のエンドポイントには推奨されません。

ルーティング

既定の動作

既定で、関数バインディングでは DefaultEndpointRouter を使用してエンドポイントを選択します。

  • クライアント ルーティング: プライマリ オンライン エンドポイントから 1 つのエンドポイントをランダムに選択します。 すべてのプライマリ エンドポイントがオフラインの場合は、セカンダリ オンライン エンドポイントを 1 つランダムに選択します。 選択が再び失敗すると、例外がスローされます。

  • サーバー メッセージ ルーティング: すべてのサービス エンドポイントが返されます。

カスタマイズ

C# インプロセス モデル

次に手順を示します。

  1. カスタマイズされたルーターを実装します。 ServiceEndpoint から提供される情報を利用して、ルーティングを決定できます。 こちらのガイドを参照してください: customize-route-algorithmカスタム ネゴシエーション メソッドで HttpContext が必要な場合は、ネゴシエーション関数で HTTP トリガーが必要であることに注意してください。

  2. ルーターを 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>();
        }
    }
}
分離プロセス モデル

分離プロセス モデルで実行される関数の場合、各要求でターゲット エンドポイントを指定することがサポートされています。 新しいバインディングの種類を使用してエンドポイント情報を取得します。

クライアント ルーティング

SignalRConnectionInfo バインディングの場合、既定のルーティング規則に従って 1 つのエンドポイントが選択されます。 ルーティング規則をカスタマイズする場合は、SignalRConnectionInfo バインディングではなく SignalRNegotiation バインディングを使用する必要があります。

SignalRNegotiation バインディング構成プロパティは SignalRConnectionInfo と同じです。 function.json ファイルのサンプルを次に示します。

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

SignalRConnectionInfo と同様に、userIdidTokenclaimTypeList などの他のバインディング データを追加することもできます。

SignalRNegotiation バインディングから取得するオブジェクトの形式は次のとおりです。

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

SignalRNegotiation バインディングの JavaScript 使用サンプルを次に示します。

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;
    }
}
メッセージのルーティング

メッセージまたはアクションのルーティングが連携するには、2 つのバインディングの種類が必要です。 一般に、使用できるすべてのエンドポイント情報を取得するには、まず新しい入力バインディングの種類 SignalREndpoints が必要です。 次に、エンドポイントをフィルター処理して、送信先のすべてのエンドポイントを含む配列を取得します。 最後に、SignalR 出力バインディングでターゲット エンドポイントを指定します。

functions.json ファイル内の SignalREndpoints バインディング構成プロパティは次のとおりです。

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

SignalREndpoints から取得するオブジェクトはエンドポイントの配列であり、それぞれ次のスキーマを持つ JSON オブジェクトとして表されます。

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

ターゲット エンドポイント配列を取得した後、出力バインディング オブジェクトに endpoints プロパティを追加します。 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();
}

Management SDK の場合

構成から複数のエンドポイントを追加する

SignalR Service 接続文字列のキー Azure:SignalR:Endpoints を使用して構成します。 キーの形式は Azure:SignalR:Endpoints:{Name}:{EndpointType} にする必要があります。この NameEndpointTypeServiceEndpoint オブジェクトのプロパティであり、コードからアクセスできます。

次の dotnet コマンドを使用して、複数のインスタンス接続文字列を追加できます。

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>

コードから複数のエンドポイントを追加する

ServiceEndpoint クラスには、Azure SignalR Service エンドポイントのプロパティが示されています。 次のように、Azure SignalR Management SDK を使用して複数のインスタンス エンドポイントを構成できます。

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

エンドポイント ルーターをカスタマイズする

既定では、SDK では DefaultEndpointRouter を使用してエンドポイントを選択します。

既定の動作

  • クライアント要求のルーティング:

    クライアントがアプリ サーバーを使用して /negotiate すると、 既定では、SDK は使用可能な一連のサービス エンドポイントから 1 つのエンドポイントをランダムに選択します。

  • サーバー メッセージのルーティング:

    特定の接続にメッセージを送信すると、ターゲット接続は現在のサーバーにルーティングされ、メッセージは接続済みエンドポイントに直接送信されます。 それ以外の場合、メッセージはすべての Azure SignalR エンドポイントにブロードキャストされます。

ルーティング アルゴリズムをカスタマイズする

メッセージの送信先エンドポイントを特定する特別な知識を持っている場合は、独自のルーターを作成できます。

次の例では、east- で始まるグループのメッセージを 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);
    }
}

次の例では、既定のネゴシエート動作をオーバーライドし、アプリ サーバーの場所に応じてエンドポイントを選択します。

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

次のように、必ずルーターを DI コンテナーに登録してください。

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

リージョンをまたがるシナリオでの構成

ServiceEndpoint オブジェクトには、EndpointType プロパティがあり、primary または secondary の値を持ちます。

プライマリ エンドポイントは、より信頼性の高いネットワーク接続を備えているため、クライアント トラフィックを受信するためのエンドポイントとして優先されます。 セカンダリ エンドポイントは、ネットワーク接続の信頼性が低く、サーバーからクライアントへのトラフィックにのみ使用されます。 たとえば、セカンダリ エンドポイントは、クライアントからサーバーへのトラフィックではなく、メッセージのブロードキャストに使用されます。

リージョンをまたがるケースでは、ネットワークが不安定になる場合があります。 米国東部に配置されているアプリ サーバーの場合、同じ米国東部リージョンに配置された SignalR Service エンドポイントが primary であり、他のリージョンにあるエンドポイントは secondary として設定されます。 この構成では、他のリージョンのサービス エンドポイントはこの米国東部のアプリ サーバーからのメッセージを受信できますが、リージョンをまたがるクライアントはこのアプリ サーバーにルーティングされません。 このアーキテクチャを次の図に示します。

地域をまたがるインフラ

クライアントが既定のルーターを使用してアプリ サーバーとの /negotiate を試行すると、SDK は使用可能な一連の primary エンドポイントから 1 つのエンドポイントをランダムに選択します。 プライマリ エンドポイントが使用できない場合、SDK は使用可能なすべての secondary エンドポイントからランダムに選択します。 サーバーとサービス エンドポイント間の接続が保持されている場合、エンドポイントは使用可能としてマークされます。

リージョンをまたがるシナリオでは、米国東部でホストされているアプリ サーバーとの /negotiate をクライアントが試行すると、既定では、同じリージョンに配置されている primary エンドポイントが常に返されます。 米国東部のすべてのエンドポイントが使用不可の場合、ルーターはクライアントを他のリージョンのエンドポイントにリダイレクします。 次の「フェールオーバー」セクションでこのシナリオについて詳しく説明します。

通常のネゴシエート

[フェールオーバー]

使用可能な primary エンドポイントがない場合、クライアントの /negotiate により使用可能な secondary エンドポイントが選択されます。 このフェールオーバー メカニズムでは、各エンドポイントが少なくとも 1 つのアプリ サーバーに対する primary エンドポイントとして機能する必要があります。

フェールオーバー メカニズム プロセスを示す図。

次のステップ

高可用性およびディザスター リカバリーのシナリオで複数のエンドポイントを使用できます。