Skip to main content
Version: 4.x

连接状态恢复

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

¥Connection state recovery is a feature which allows restoring a client's state after a temporary disconnection, including any missed packets.

info

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

¥This feature was added in version 4.6.0, released in February 2023.

发行说明可以找到 此处

¥The release notes can be found here.

免责声明

¥Disclaimer

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

¥Under real conditions, a Socket.IO client will inevitably experience temporary disconnections, regardless of the quality of the connection.

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

¥This feature will help you cope with such disconnections, but unless you want to store the packets and the sessions forever (by setting maxDisconnectionDuration to Infinity), you can't be assured that the recovery will always be successful.

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

¥That's why you will still need to handle the case where the states of the client and the server must be synchronized.

用法

¥Usage

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

¥Connection state recovery must be enabled by the server:

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 属性。

¥Upon an unexpected disconnection (i.e. no manual disconnection with socket.disconnect()), the server will store the id, the rooms and the data attribute of the socket.

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

¥Then upon reconnection, the server will try to restore the state of the client. The recovered attribute indicates whether this recovery was successful:

服务器

¥Server

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

客户端

¥Client

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

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

¥You can check that the recovery is working by forcefully closing the underlying engine:

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);
});
tip

你还可以直接在浏览器中运行此示例:

¥You can also run this example directly in your browser on:

与现有适配器的兼容性

¥Compatibility with existing adapters

适配器支持?
内置适配器(在内存中)是:白色复选标记:
Redis 适配器1
Redis 流适配器是:白色复选标记:
MongoDB 适配器是:白色复选标记:(自版本 0.3.0 起)
Postgres 适配器在制品
集群适配器在制品

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

¥[1] Persisting the packets is not compatible with the Redis PUB/SUB mechanism.

它是如何工作的

¥How it works under the hood

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

    ¥the server sends a session ID during the handshake (which is different from the current id attribute, which is public and can be freely shared)

示例:

¥Example:

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
  • 服务器还包括 每个数据包 中的偏移量(添加在数据数组的末尾,以实现向后兼容性)

    ¥the server also includes an offset in each packet (added at the end of the data array, for backward compatibility)

示例:

¥Example:

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
note

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

¥For the recovery to succeed, the server must send at least one event, in order to initialize the offset on the client side.

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

    ¥upon temporary disconnection, the server stores the client state for a given delay (implemented at the adapter level)

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

    ¥upon reconnection, the client sends both the session ID and the last offset it has processed, and the server tries to restore the state

示例:

¥Example:

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