gpt4 book ai didi

node.js - Firestore 实时更新 NodeJS 中的连接

转载 作者:行者123 更新时间:2023-12-01 13:16:20 24 4
gpt4 key购买 nike

我正在开发一个 NodeJS Web 应用程序,以通过 Admin SDK 从 Firestore DB 接收实时更新。

这是 Firestore 对象的初始化代码。在部署应用程序时(在 AWS Elastic Beanstalk 上),它只执行一次:

const admin = require('firebase-admin');

var serviceAccount = require('./../key.json');

admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});

var db = admin.firestore();

FUNC.firestore = db;

然后我在 websocket 通信中使用这个 firestore 对象向浏览器发送实时更新。这个想法是使用服务器作为浏览器和 Firestore 之间的代理。
socket.on('open', function (client) {
var query = FUNC.firestore.collection("notifications").doc(client.user.id.toString()).collection("global");
query.onSnapshot(querySnapshot => {
querySnapshot.docChanges().forEach(change => {
client.send({ id: change.doc.id, body: change.doc.data(), type: change.type });
});
}, err => {
console.log(`Encountered error: ${err}`);
});
});

socket.on('close', function (client) {
var unsub = FUNC.firestore.collection("notifications").doc(client.user.id.toString()).collection("global").onSnapshot(() => {
});
unsub();
});

它运行了一段时间,但几个小时后客户端停止接收 onSnapshot()更新,一段时间后服务器记录错误: Encountered error: Error: 10 ABORTED: The operation was aborted.
怎么了?我应该在每个连接上初始化 firestore 吗?是否存在生命周期错误?

谢谢

编辑(一个非常糟糕的解决方案)

我尝试为每个登录的用户创建一个 firebase-admin 应用程序实例,并以这种方式更改了我的代码
const admin = require('firebase-admin');

var serviceAccount = require('./../key.json');

admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});

FUNC.getFirestore = function (user) {
try {
user.firebase = admin.app(user.id.toString());
return user.firebase.firestore();
} catch(e) {
//ignore
}

var app = admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
}, user.id.toString());

user.firebase = app;

return user.firebase.firestore();
}

FUNC.removeFirebase = function (user) {
if (user.firebase) {
user.firebase.delete();
}
}

然后是套接字监听器:
    self.on('open', function (client) {
var query = FUNC.getFirestore(client.user).collection("notifications").doc(client.user.id.toString()).collection("global");
query.onSnapshot(querySnapshot => {
querySnapshot.docChanges().reverse();
querySnapshot.docChanges().forEach(change => {
client.send({ id: change.doc.id, body: change.doc.data(), type: change.type });
});
}, err => {
console.log(`Encountered error: ${err}`);
});
});

self.on('close', function (client) {
var unsub = FUNC.getFirestore(client.user).collection("notifications").doc(client.user.id.toString()).collection("global").onSnapshot(() => {
});
unsub();
FUNC.removeFirebase(client.user);
});

因此,当客户端因某种原因断开连接时,服务器会删除其 Firebase 应用程序,它可以工作,但我注意到 巨大的服务器内存泄漏,我需要一些帮助

最佳答案

更新的答案

经过多次研究,我明白这种方法是 .当然,旧的答案可能是一种解决方法,但不是问题的真正解决方案,因为 Firestore 并非旨在执行以下操作:Firestore <--(Admin SDK)--> Server <--(WebSocket)--> Client .

为了创建最佳通信,我了解并应用了 Firestore 安全规则 ( https://firebase.google.com/docs/firestore/security/get-started ) 和自定义 token 生成 ( https://firebase.google.com/docs/auth/admin/create-custom-tokens )。所以正确的流程是:

Client login request --> Server + Admin SDK generate custom auth token and return to client

然后,实时通信将仅在 Client 和 Firestore 本身之间进行,因此: Client + Custom Auth Token <--(Firebase JS SDK)--> Firestore DB
如您所见,服务器不再参与实时通信,但客户端直接从 Firestore 接收更新。

旧答案

终于可以自己回答了。首先,我尝试过的第二种解决方案非常糟糕,因为通过 Admin SDK 创建的每个新应用程序都存储在 RAM 中,有 20/30 的用户,该应用程序的 RAM 超过 1GB,绝对不能接受。

所以第一个实现是更好的解决方案,无论如何我错误地注册/取消注册 onSnapshot 监听器生命周期。每个 onSnapshot() call 返回一个不同的函数,即使在同一个引用上调用。因此,我没有在套接字关闭时关闭监听器,而是打开了另一个监听器。应该是这样:
socket.on('open', function (client) {
var query = FUNC.firestore.collection("notifications").doc(client.user.id.toString()).collection("global");
client.user.firestoreUnsub = query.onSnapshot(querySnapshot => {
querySnapshot.docChanges().forEach(change => {
client.send({ id: change.doc.id, body: change.doc.data(), type: change.type });
});
}, err => {
console.log(`Encountered error: ${err}`);
});
});

socket.on('close', function (client) {
client.user.firestoreUnsub();
});

将近 48 小时后,监听器仍然可以正常工作并且没有发生内存泄漏。

关于node.js - Firestore 实时更新 NodeJS 中的连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54629241/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com