连接状态恢复
连接状态恢复是一项允许在临时断开连接后恢复客户端状态的功能,包括任何丢失的数据包。
¥Connection state recovery is a feature which allows restoring a client's state after a temporary disconnection, including any missed packets.
免责声明
¥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);
});
与现有适配器的兼容性
¥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
为了成功恢复,服务器必须发送至少一个事件,以便初始化客户端的偏移量。
¥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