跳至主要内容
版本:4.x

连接状态恢复

连接状态恢复是一项功能,允许在临时断开连接后恢复客户端的状态,包括任何错过的数据包。

信息

此功能在 2023 年 2 月发布的 4.6.0 版本中添加。

发行说明可以在 这里找到。

免责声明

在实际情况下,Socket.IO 客户端不可避免地会遇到临时断开连接,无论连接质量如何。

此功能将帮助您应对此类断开连接,但除非您想永久存储数据包和会话(通过将 maxDisconnectionDuration 设置为 Infinity),否则无法保证恢复始终成功。

这就是为什么您仍然需要处理客户端和服务器状态必须同步的情况。

用法

连接状态恢复必须由服务器启用

const io = new Server(httpServer, {
connectionStateRecovery: {
// the backup duration of the sessions and the packets
maxDisconnectionDuration: 2 * 60 * 1000,
// whether to skip middlewares upon successful recovery
skipMiddlewares: true,
}
});

在意外断开连接(即没有使用 socket.disconnect() 手动断开连接)时,服务器将存储套接字的 id、房间和 data 属性。

然后在重新连接时,服务器将尝试恢复客户端的状态。recovered 属性指示此恢复是否成功

服务器

io.on("connection", (socket) => {
if (socket.recovered) {
// recovery was successful: socket.id, socket.rooms and socket.data were restored
} else {
// new or unrecoverable session
}
});

客户端

socket.on("connect", () => {
if (socket.recovered) {
// any event missed during the disconnection period will be received now
} else {
// new or unrecoverable session
}
});

您可以通过强制关闭底层引擎来检查恢复是否正常工作

import { io } from "socket.io-client";

const socket = io({
reconnectionDelay: 10000, // defaults to 1000
reconnectionDelayMax: 10000 // defaults to 5000
});

socket.on("connect", () => {
console.log("recovered?", socket.recovered);

setTimeout(() => {
if (socket.io.engine) {
// close the low-level connection and trigger a reconnection
socket.io.engine.close();
}
}, 10000);
});
提示

您也可以在浏览器中直接运行此示例

与现有适配器的兼容性

适配器支持?
内置适配器(内存中)是 ✅
Redis 适配器1
Redis Streams 适配器是 ✅
MongoDB 适配器是 ✅ (从版本 0.3.0 开始)
Postgres 适配器进行中
集群适配器进行中

[1]持久化数据包与 Redis PUB/SUB 机制不兼容。

幕后工作原理

  • 服务器在 握手期间 发送一个会话 ID(这与当前的 id 属性不同,当前的 id 属性是公开的,可以自由共享)

示例

40{"sid":"GNpWD7LbGCBNCr8GAAAB","pid":"YHcX2sdAF1z452-HAAAW"}

where

4 => the Engine.IO message type
0 => the Socket.IO CONNECT type
GN...AB => the public id of the session
YH...AW => the private id of the session
  • 服务器还在 每个数据包 中包含一个偏移量(添加到数据数组的末尾,以实现向后兼容)

示例

42["foo","MzUPkW0"]

where

4 => the Engine.IO message type
2 => the Socket.IO EVENT type
foo => the event name (socket.emit("foo"))
MzUPkW0 => the offset
注意

为了使恢复成功,服务器必须至少发送一个事件,以便在客户端侧初始化偏移量。

  • 在临时断开连接时,服务器会将客户端状态存储在给定的延迟时间内(在适配器级别实现)

  • 在重新连接时,客户端会发送会话 ID 和它已处理的最后一个偏移量,服务器会尝试恢复状态

示例

40{"pid":"YHcX2sdAF1z452-HAAAW","offset":"MzUPkW0"}

where

4 => the Engine.IO message type
0 => the Socket.IO CONNECT type
YH...AW => the private id of the session
MzUPkW0 => the last processed offset