Redis Backplaneによるスケーリング
Redis Backplaneを使ってインスタンス間のメッセージを同期し、複数サーバーにまたがってSignalRをスケールさせます。
「Redis Backplaneによるスケーリング」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。
マルチサーバーの問題
SignalR が単一のサーバーで動作している場合、クライアントとサーバーは接続やグループの情報をメモリ上で共有します。しかし、サーバーを2台以上にスケールすると、各サーバーは自分自身の接続しか把握できません。そのため、Server A で送信したメッセージは Server B に接続しているクライアントには届きません。
バックプレーンとは
バックプレーンとは、SignalR サーバーインスタンス間で共有されるメッセージバスです。あるサーバーがメッセージを送信するとき、バックプレーンに公開します。すべてのサーバーがそのメッセージを受信し、それぞれのローカル接続へ転送します。
Redis バックプレーンの追加
Microsoft.AspNetCore.SignalR.StackExchangeRedis パッケージをインストールし、AddSignalR() の後に AddStackExchangeRedis() を呼び出します。
// dotnet add package Microsoft.AspNetCore.SignalR.StackExchangeRedis
builder.Services.AddSignalR()
.AddStackExchangeRedis("localhost:6379", options =>
{
options.Configuration.ChannelPrefix =
RedisChannel.Literal("myapp"); // namespace your channels
});
// Or from config:
// .AddStackExchangeRedis(builder.Configuration.GetConnectionString("Redis")!);SignalR で Redis Pub/Sub が動作する仕組み
各 SignalR サーバーは Redis チャネルを購読します。Server A がグループまたはユーザー宛てのメッセージを公開すると、Redis はすべての購読者(Server B、Server C など)に配信し、それらのサーバーがローカル接続へ転送します。
// Server A: client sends message
// Hub on Server A calls:
await Clients.Group("room-42").ReceiveMessage(user, msg);
// Internally SignalR publishes to Redis:
// PUBLISH signalr/myapp/group/room-42 <serialized message>
// Redis delivers to Server B and C
// Both servers find connections in "room-42" and push to them構成オプション
本番環境向けに Redis 接続を細かく調整できます。TLS、パスワード、接続の回復性、Pub/Sub チャネルのプレフィックスなどを設定します。
builder.Services.AddSignalR()
.AddStackExchangeRedis(opts =>
{
opts.Configuration = ConfigurationOptions.Parse(
builder.Configuration["Redis:ConnectionString"]!);
opts.Configuration.Password = builder.Configuration["Redis:Password"];
opts.Configuration.Ssl = true;
opts.Configuration.AbortOnConnectFail = false;
opts.Configuration.ConnectRetry = 3;
});Azure SignalR Service
完全に管理されたスケーリングには、Azure SignalR Service を使用します。Azure SignalR Service がバックプレーンと接続マネージャーとして機能するため、アプリケーションサーバーはステートレスになり、WebSocket 接続自体を保持する必要がありません。
// dotnet add package Microsoft.Azure.SignalR
builder.Services.AddSignalR()
.AddAzureSignalR(builder.Configuration["Azure:SignalR:ConnectionString"]!);
// That's it — Azure manages all connections and backplane
// Your server scales to zero when not neededスティッキーセッション(WebSocket 以外のトランスポート向けのフォールバック)
Server-Sent Events または Long Polling(WebSocket ではない)を使用する場合、同じクライアントは常に同じサーバーへ接続する必要があります。これをスティッキーセッションと呼びます。ロードバランサーまたはリバースプロキシで設定してください。
# Nginx: sticky session config (IP hash)
upstream signalr_servers {
ip_hash; # ensures same client hits same server
server server1:5000;
server server2:5000;
server server3:5000;
}
# Or use cookie-based sticky sessions:
# sticky cookie srv_id expires=1h;
# WebSockets don't need sticky sessions —
# the connection is long-lived on one server複数サーバー間でのグループ
グループメンバーシップはバックプレーンによって維持されます。Server A で接続をグループに追加すると、Redis を介して Server B にもその情報が伝わります。アプリケーションコードからは透過的に利用できます。
// This works correctly across servers:
public async Task JoinRoom(string room)
{
// Adds to Redis-backed group
await Groups.AddToGroupAsync(Context.ConnectionId, room);
// Clients.Group sends via Redis to all servers
await Clients.Group(room).UserJoined(Context.User!.Identity!.Name!);
}
// No code changes needed — the Redis backplane handles distributionRedis Pub/Sub の監視
Redis チャネルを監視して、SignalR のトラフィックを確認し、問題を診断します。redis-cli SUBSCRIBE または Redis Insights を使用して、メッセージの流れを観察できます。
# redis-cli: monitor all SignalR channels
redis-cli PSUBSCRIBE "myapp*"
# Check active channel subscribers
redis-cli PUBSUB CHANNELS "myapp*"
# Check number of subscribers per channel
redis-cli PUBSUB NUMSUB "myapp/all"Redis 障害への対処
Redis が利用できなくなると、SignalR はローカルのみのモードにフォールバックし、サーバー間でメッセージが伝達されなくなります。Redis 接続のための再試行ポリシーとアラートを設定してください。
builder.Services.AddSignalR()
.AddStackExchangeRedis(opts =>
{
opts.Configuration = ConfigurationOptions.Parse(redisConn);
opts.Configuration.AbortOnConnectFail = false; // don't crash app
opts.Configuration.ConnectRetry = 5;
opts.Configuration.ReconnectRetryPolicy =
new ExponentialRetry(5000, maxDeltaBackoffMilliseconds: 60000);
});実践例:スケールしたチャットアーキテクチャ
本番環境では、ロードバランサーの背後で3台以上の SignalR サーバーインスタンスを実行し、Redis(または Azure SignalR Service)をバックプレーンとして使用します。すべての状態は Redis に保存し、サーバーはステートレスかつ使い捨て可能にします。
// Architecture:
// [Browser] -> [Load Balancer (any server, WebSocket)] ->
// [SignalR Server 1] -+
// [SignalR Server 2] -+-> [Redis Pub/Sub] -> all servers
// [SignalR Server 3] -+
// Server code is identical on all instances:
builder.Services.AddSignalR().AddStackExchangeRedis(redisConn);
app.MapHub<ChatHub>("/hubs/chat");
// Scale replicas: kubectl scale deployment chat --replicas=3確認問題
SignalR のバックプレーンは、どのような問題を解決しますか?
まとめ:Redis バックプレーンによるスケーリング
主なポイント:
- バックプレーンがない場合、あるサーバーからのメッセージは別のサーバー上のクライアントに届きません
- AddStackExchangeRedis() によって、Redis Pub/Sub バックプレーンが透過的に追加されます
- Azure SignalR Service は、完全に管理されたサーバーレスのバックプレーンという選択肢を提供します
- WebSocket 以外のトランスポート(SSE、Long Polling)では、スティッキーセッションが必要です
- バックプレーンを介して、サーバー間でグループメンバーシップが同期されます
- Redis の回復性を高めるため、AbortOnConnectFail=false と再試行ポリシーを設定します
よくある質問
「Redis Backplaneによるスケーリング」レッスンは無料ですか?
はい。「Redis Backplaneによるスケーリング」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。
「Redis Backplaneによるスケーリング」で何を学びますか?
Redis Backplaneを使ってインスタンス間のメッセージを同期し、複数サーバーにまたがってSignalRをスケールさせます。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C# Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「Redis Backplaneによるスケーリング」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC# Academyレッスンでコードを書いて実行できますか?
はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- SignalR Hubと接続
- グループ、ユーザーと接続管理
- 型付きHub
- Redis Backplaneによるスケーリング