メインコンテンツへスキップ
バージョン: 4.x

接続状態の復旧

接続状態の復旧は、一時的な切断後に、クライアントの状態(見逃したパケットを含む)を復元できる機能です。

情報

この機能は、2023年2月にリリースされたバージョン 4.6.0 で追加されました。

リリースノートはこちらにあります。

免責事項

実際の状況では、Socket.IOクライアントは、接続品質に関係なく、一時的な切断を必然的に経験します。

この機能は、そのような切断に対処するのに役立ちますが、パケットとセッションを永久に保存したい場合(maxDisconnectionDurationInfinityに設定することで)、復旧が常に成功することを保証することはできません。

そのため、クライアントとサーバーの状態を同期する必要がある場合に対処する必要があります。

使い方

接続状態の復旧は、サーバーで有効にする必要があります。

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 アダプター作業中
Cluster アダプター作業中

[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
注意

復旧を成功させるには、サーバーが少なくとも1つのイベントを送信して、クライアント側のオフセットを初期化する必要があります。

  • 一時的な切断が発生すると、サーバーはクライアントの状態を特定の遅延時間だけ保存します(アダプターレベルで実装)。

  • 再接続時に、クライアントはセッション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