sgcWebSockets 消息历史与重连恢复 — 永不漏掉任何消息 | eSeGeCe 博客

sgcWebSockets 消息历史与重连恢复 — 永不漏掉任何消息

· 组件

真实的 WebSocket 客户端时时刻刻都在断开连接:手机锁屏、Wi-Fi 切换到蜂窝网络、隧道出现卡顿、强制门户网站挡在中间。当连接恢复时,客户端离线期间发布的消息就丢失了。"我手机锁屏时漏掉了消息"是用户最先注意到的故障,而通常的变通办法 — 在每次重连时重新拉取整个状态 — 既浪费资源又容易出错。

sgcWebSockets 现在直接解决了这个问题。在服务器上启用历史,重连的客户端就会按偏移量自动精确重放它错过的消息。它是可选启用、默认关闭的,因此在你打开它之前,现有部署的行为与以前完全一致。本文将介绍它的工作原理、配置方法,以及 Delphi 和 .NET 示例。

工作原理

当启用历史后,发布到某个通道的每条消息都会被打上一个单调递增的偏移量,并追加到服务器上每个通道的有界环形缓冲区中。客户端会记住它在每个通道上收到的最后一个偏移量。当它重连并重新订阅时,会发送该偏移量,服务器则把所有更新的消息重放给那一个连接 — 按顺序、不重复。

偏移量由客户端携带,因此没有需要管理的服务器端会话。恢复只是一次普通的重新订阅。

在服务器上启用历史

历史位于 sgc 协议服务器上的 History 选项对象下。打开它,并按消息数量和 / 或时间长度对其设限:

uses
  sgcWebSocket, sgcWebSocket_Protocols;

var
  oProtocol: TsgcWSPServer_sgc;
begin
  oProtocol := TsgcWSPServer_sgc.Create(nil);
  oProtocol.Server := oServer;

  oProtocol.History.Enabled    := True;
  oProtocol.History.Size       := 1000;   // keep the last 1000 messages per channel
  oProtocol.History.TTLSeconds := 3600;   // optional: also drop entries older than 1 hour
end;

Size 限制了每个通道的内存占用(它同时也为以前那个无界队列设定了上限);TTLSeconds 是一个可选的时间长度限制。当历史被禁用时(默认情况),线路上不携带偏移量,行为也没有任何改变。

客户端上的自动恢复

客户端会替你跟踪偏移量。重连之后,一次普通的 Subscribe 就会自动请求服务器重放该通道上错过的任何内容 — 你无需跟踪或传递任何东西:

// On (re)connect, just resubscribe. The client auto-sends the last offset it saw,
// and the server replays the messages published while the client was offline.
sgcWSPClient_sgc1.Subscribe('news');

// Or request the full retained history explicitly (cursor 0 = everything kept):
sgcWSPClient_sgc1.Subscribe('news', 0);

每个通道的偏移量映射在断开连接后依然保留,因此重连并重新订阅就足够了。如果你想显示或持久化游标,GetLastOffset('news') 会把它暴露出来。

.NET

托管版镜像了相同的 API。在服务器协议上启用历史,客户端就会在重新订阅时恢复:

var protocol = new TsgcWSPServer_sgc { Server = server };
protocol.History.Enabled    = true;
protocol.History.Size       = 1000;
protocol.History.TtlSeconds = 3600;

// Client: a plain resubscribe after reconnect recovers the missed messages.
client.Subscribe("news");
long last = client.GetLastOffset("news");

可选启用,默认安全

历史默认关闭。当它关闭时,发布的帧不携带偏移量,发布 / 订阅路径与以前逐字节一致 — 因此在你显式启用它之前,升级不会改变任何东西。当你确实启用它时,有界环形缓冲区会让内存占用保持可预测。

在多节点集群中,本次发布的历史是节点本地的:重连到同一节点的客户端可以获得完整重放。共享的全集群范围历史已列入路线图。库中附带了一个开箱即用的演示(Delphi 上的 02.WebSocket_Protocols\15.MessageHistory_Recovery,.NET 上的 samples\HistoryRecoveryDemo):它让一个客户端离线,在其离线期间发布消息,然后让它重连,并展示它如何精确恢复它错过的消息。

可用性

消息历史与重连恢复在 sgc 协议上可用,覆盖 Delphi 7 到 13(Win32/Win64、Linux64、macOS、Android 和 iOS)以及托管 .NET 版。它与 sgcWebSockets 客户端已有的 WatchDog 自动重连天然搭配。

拥有有效订阅的客户可以从客户区下载新版本。试用用户可以在 esegece.com/products/websockets/download 获取更新后的安装程序。

有疑问、反馈,或需要帮助把恢复功能接入你的应用?联系我们 — 你会收到来自编写这些代码的人的回复。