連線狀態復原
連線狀態復原是一項功能,可讓您在暫時中斷連線後還原用戶端的狀態,包括任何遺漏的封包。
資訊
此功能已新增至 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()
)時,伺服器會儲存 socket 的 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 屬性不同,後者是公開的,可以自由分享)
範例
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