在高并发协作与企业即时通讯(Chat Subsystem)中,系统面临百万级长连接与实时广播的双重压力:
- 跨服务器节点消息广播(Multi-Node Backplane):用户 A 连接在集群节点 1,用户 B 连接在节点 2,节点 1 必须将消息毫秒级路由给节点 2;
- 弱网离线与乱序同步(Offline Message Gap):移动端在电梯等弱网断线重连后,必须通过 Sequence 序号精准拉取未读消息差量,杜绝消息丢失或重复展示;
- 租户频道安全鉴权:严禁未获授权的用户通过伪造频道 ID 监听跨租户或私密频道的群聊消息。
BitzOrcas.Modern Chat 模块以“WebSocket 接入层 + Redis Backplane 广播底座 + 顺序递增消息存储”构建了高可用实时通讯引擎。
即时通讯长连接与跨节点广播拓扑
第一步:顺序消息实体 ChatMessage
消息实体采用严格递增的序列号(SequenceNo),供客户端断线增量同步:
using BitzOrcas.Domain.Entities;using BitzOrcas.Persistence.Metadata;
namespace BitzOrcas.Chat.Domain;
// 1. 声明消息流水物理表与频道唯一索引[BitzTable("SysChatMessage", IsTenant = true, IsSoftDelete = false, Description = "聊天消息流水表")][BitzIndex("IX_SysChatMessage_Channel_Seq", nameof(ChannelId), nameof(SequenceNo), IsUnique = true)]public sealed class ChatMessage : Entity<string>{ [BitzColumn(Length = 64, IsRequired = true)] public string ChannelId { get; set; } = string.Empty;
[BitzColumn(Length = 64, IsRequired = true)] public string SenderUserId { get; set; } = string.Empty;
// 2. 单频道内单调递增序号(1, 2, 3... 用于客户端增量拉取与离线同步) [BitzColumn(IsRequired = true)] public long SequenceNo { get; set; }
[BitzColumn(Length = 4000, IsRequired = true)] public string Content { get; set; } = string.Empty;
[BitzColumn(IsRequired = true)] public DateTimeOffset SentAt { get; set; }}第二步:发送消息垂直切片与跨节点广播
using BitzOrcas.Application.Abstractions.Realtime;using BitzOrcas.Domain.Results;using BitzOrcas.Chat.Domain;
public sealed class SendChatMessageCommandHandler( IChatMessageRepository messageRepo, IRealtimePublisher realtimePublisher, IAppClock clock){ public async ValueTask<Result> Handle(SendChatMessageCommand command, CancellationToken ct) { // 1. 获取当前频道下一个序列号并保存消息 var nextSeq = await messageRepo.GetNextSequenceNoAsync(command.ChannelId, ct); var msg = new ChatMessage { ChannelId = command.ChannelId, SenderUserId = command.SenderUserId, SequenceNo = nextSeq, Content = command.Content, SentAt = clock.UtcNow };
await messageRepo.SaveAsync(msg, ct);
// 2. 通过 Redis Backplane 向集群广播给频道订阅者 await realtimePublisher.PublishToChannelAsync( channel: $"chat:{command.ChannelId}", payload: new ChatMessageBroadcastDto(msg.Id, msg.SenderUserId, msg.Content, msg.SequenceNo), ct);
return Result.Success(); }}总结
Chat 模块提供低延迟与可靠性:
- 单调 Sequence 序号:离线重连通过
SyncAfter(lastSeq)精准补齐消息差量; - Redis 分布式广播:集群线性横向扩展,支撑万级并发在线;
- 多租户物理隔离:频道名称天然携带租户前缀,杜绝越权串号。