0Pricing
C# Academy · 课时

使用 Redis 后端扩展

使用 Redis 后端在多个服务器之间扩展 SignalR,在各实例之间同步消息。

使用 Redis 后端扩展 是 CoddyKit 上的免费 C# Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C# Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C# Academy 课程共包含 4 节课。

多服务器问题

当 SignalR 在单台服务器上运行时,客户端和服务器会共享连接和组的内存。扩展到两台或更多服务器后,每台服务器只知道自己的连接——在服务器 A 上发送的消息永远到不了连接到服务器 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")!);

Redis 发布/订阅如何为 SignalR 工作

每个 SignalR 服务器都会订阅 Redis 通道。当服务器 A 为组或用户发布消息时,Redis 会将其传递给所有订阅者(服务器 B、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、密码、连接容错能力以及发布/订阅通道前缀。

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 服务

如需完全托管的扩展,请使用 Azure SignalR 服务。它充当回程总线和连接管理器——您的应用服务器变为无状态,并且自身不持有 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 传输的后备方案)

使用服务器发送事件或长轮询(而非 WebSockets)时,同一客户端必须始终访问同一台服务器——这称为粘性会话。请在负载均衡器或反向代理中配置此项。

# 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

跨多台服务器的组

回程总线会维护组成员关系。在服务器 A 上将连接添加到组后,服务器 B 会通过 Redis 得知这一变化——对应用程序代码完全透明。

// 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 distribution

监控 Redis 发布/订阅

监控 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 服务)作为回程总线。所有状态都存储在 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 发布/订阅回程总线
  • Azure SignalR 服务提供完全托管的无服务器回程总线替代方案
  • 非 WebSocket 传输(SSE、长轮询)需要粘性会话
  • 通过回程总线在各服务器之间同步组成员关系
  • 配置 AbortOnConnectFail=false 和重试策略,以增强 Redis 的容错能力

常见问题解答

「使用 Redis 后端扩展」课时是免费的吗?

是的 — 「使用 Redis 后端扩展」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C# Academy 课程的其余内容,请升级到 CoddyKit PRO。 C# Academy 课程共包含 4 节课。

「使用 Redis 后端扩展」这节课中我会学到什么?

使用 Redis 后端在多个服务器之间扩展 SignalR,在各实例之间同步消息。 你通过在浏览器中直接运行的动手代码来练习 C# Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 C# Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 C# Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「使用 Redis 后端扩展」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 C# Academy 课中编写并运行代码吗?

能。每节 C# Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. SignalR 中心与连接
  2. 组、用户与连接管理
  3. 强类型中心
  4. 使用 Redis 后端扩展
← 返回 C# Academy