转到主要内容
版本:4.x

MongoDB 适配器

这个怎么运作

MongoDB 适配器依赖于 MongoDB 的变更流(因此需要副本集或分片集群)。

每个发送给多个客户的数据包 (例如 io.to("room1").emit()socket.broadcast.emit()) 是:

  • 发送到连接到当前服务器的所有匹配客户端
  • 插入到 MongoDB capped 集合中,并由集群的其他 Socket.IO 服务器接收

Diagram of how the MongoDB adapter works

这个适配器的源代码可以在这里找到。

安装

npm install @socket.io/mongo-adapter mongodb

对于 TypeScript 用户,您可能还需要@types/mongodb.

用法

有两种方法可以清理适配器创建的 MongoDB 文档:

使用 capped collection

const { Server } = require("socket.io");
const { createAdapter } = require("@socket.io/mongo-adapter");
const { MongoClient } = require("mongodb");

const DB = "mydb";
const COLLECTION = "socket.io-adapter-events";

const io = new Server();

const mongoClient = new MongoClient("mongodb://localhost:27017/?replicaSet=rs0");

const main = async () => {
await mongoClient.connect();

try {
await mongoClient.db(DB).createCollection(COLLECTION, {
capped: true,
size: 1e6
});
} catch (e) {
// collection already exists
}
const mongoCollection = mongoClient.db(DB).collection(COLLECTION);

io.adapter(createAdapter(mongoCollection));
io.listen(3000);
}

main();

使用 TTL index

const { Server } = require("socket.io");
const { createAdapter } = require("@socket.io/mongo-adapter");
const { MongoClient } = require("mongodb");

const DB = "mydb";
const COLLECTION = "socket.io-adapter-events";

const io = new Server();

const mongoClient = new MongoClient("mongodb://localhost:27017/?replicaSet=rs0");

const main = async () => {
await mongoClient.connect();

const mongoCollection = mongoClient.db(DB).collection(COLLECTION);

await mongoCollection.createIndex(
{ createdAt: 1 },
{ expireAfterSeconds: 3600, background: true }
);

io.adapter(createAdapter(mongoCollection, {
addCreatedAtField: true
}));
io.listen(3000);
}

main();

配置

配置项描述默认值添加于
uid此节点的 ID一个随机的 idv0.1.0
requestsTimeout服务器间请求的超时时间,例如fetchSockets()serverSideEmit()5000v0.1.0
heartbeatInterval两次心跳之间的毫秒数5000v0.1.0
heartbeatTimeout在我们考虑节点关闭之前没有心跳的毫秒数10000v0.1.0
addCreatedAtField是否为每个 MongoDB 文档添加一个createdAt字段falsev0.2.0

常见问题

  • 使用 MongoDB 适配器时是否还需要启用粘性会话?

是的。否则将导致 HTTP 400 响应(您到达的服务器不知道 Socket.IO 会话)。

更多信息可以在这里找到。

  • 当 MongoDB 集群宕机时会发生什么?

如果与 MongoDB 集群的连接被切断,行为将取决于MongoDB 客户端选项bufferMaxEntries的值:

  • 如果其值为-1(默认),则数据包将被缓冲直到重新连接。
  • 如果其值为0,则数据包将仅发送到连接到当前服务器的客户端。

文档: http://mongodb.github.io/node-mongodb-native/3.6/api/global.html#MongoClientOptions

最新版本

Emitter

MongoDB 发射器允许从另一个 Node.js 进程向连接的客户端发送数据包:

Diagram of how the MongoDB emitter works

安装

npm install @socket.io/mongo-emitter mongodb

用法

const { Emitter } = require("@socket.io/mongo-emitter");
const { MongoClient } = require("mongodb");

const mongoClient = new MongoClient("mongodb://localhost:27017/?replicaSet=rs0");

const main = async () => {
await mongoClient.connect();

const mongoCollection = mongoClient.db("mydb").collection("socket.io-adapter-events");
const emitter = new Emitter(mongoCollection);

setInterval(() => {
emitter.emit("ping", new Date());
}, 1000);
}

main();

请参阅此处的备忘单。