连接状态恢复

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

免责声明

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

这个功能可以帮助你应对这种断开连接的情况,但除非你想永远存储数据包和会话(通过设置 maxDisconnectionDurationInfinity),否则你不能保证恢复总是会成功的。

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

用法

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

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

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

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

服务端

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

客户端

  1. socket.on("connect", () => {
  2. if (socket.recovered) {
  3. // any missed packets will be received
  4. } else {
  5. // new or unrecoverable session
  6. }
  7. });

你可以通过强行关闭底层引擎来检查恢复是否有效:

  1. import { io } from "socket.io-client";
  2. const socket = io({
  3. reconnectionDelay: 10000, // defaults to 1000
  4. reconnectionDelayMax: 10000 // defaults to 5000
  5. });
  6. socket.on("connect", () => {
  7. console.log("recovered?", socket.recovered);
  8. setTimeout(() => {
  9. if (socket.io.engine) {
  10. // close the low-level connection and trigger a reconnection
  11. socket.io.engine.close();
  12. }
  13. }, 10000);
  14. });

连接状态恢复 - 图1提示

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

与现有适配器的兼容性

适配器是否支持?
内置适配器 (内存中)是 ✅
Redis 适配器1
MongoDB 适配器是 ✅ (since version 0.3.0)
Postgres 适配器开发中
Cluster 适配器开发中

[1] 持久数据包与Redis PUB/SUB机制不兼容,所以我们将在Redis Streams的基础上创建一个新的适配器,它将支持这一功能。

它的工作原理是什么

  • 服务器端在握手过程中发送一个会话ID(这与当前的id属性不同,后者是公开的,可以自由分享)。

示例:

  1. 40{"sid":"GNpWD7LbGCBNCr8GAAAB","pid":"YHcX2sdAF1z452-HAAAW"}
  2. where
  3. 4 => the Engine.IO message type
  4. 0 => the Socket.IO CONNECT type
  5. GN...AB => the public id of the session
  6. YH...AW => the private id of the session
  • 服务器在每个数据包 中还包括一个偏移量(为了向后兼容,在数据阵列的末尾添加)。

示例:

  1. 42["foo","MzUPkW0"]
  2. where
  3. 4 => the Engine.IO message type
  4. 2 => the Socket.IO EVENT type
  5. foo => the event name (socket.emit("foo"))
  6. MzUPkW0 => the offset
  • 在临时断开连接时,服务器端会在给定的延迟内存储客户端状态(在适配器级别实现)

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

示例:

  1. 40{"pid":"YHcX2sdAF1z452-HAAAW","offset":"MzUPkW0"}
  2. where
  3. 4 => the Engine.IO message type
  4. 0 => the Socket.IO CONNECT type
  5. YH...AW => the private id of the session
  6. MzUPkW0 => the last processed offset