【发布时间】:2019-10-11 05:20:13
【问题描述】:
我正在尝试为我的移动应用创建一些 API。我正在使用 Node+Express+Mongo+Firebase。根据其他地方 (How to properly reuse connection to Mongodb across NodeJs application and modules) 的建议,我创建了以下代码结构:
这就是我的 mongoUtils.js 中的内容:
const MongoClient = require('mongodb').MongoClient
const uri = "mongodb+srv://user:password@blabla.azure.mongodb.net/bla?retryWrites=true&w=majority";
let _db
const connectDB = async (callback) => {
try {
MongoClient.connect(uri,{ useNewUrlParser: true }, (err, client) => {
_db = client.db('ABC');
return callback(err)
})
} catch (e) {
throw e
}
}
const getDB = () => _db
const disconnectDB = () => _db.close()
module.exports = { connectDB, getDB, disconnectDB }
这就是我在 index.js 中的内容:
const functions = require('firebase-functions');
const express = require('express');
const app = express();
var cors = require('cors');
app.use(cors());
const admin = require('firebase-admin');
const bodyParser = require('body-parser')
const assert = require('assert');
const MongoDB = require('./db/mongoUtils')
admin.initializeApp(functions.config().firebase);
app.use(bodyParser.urlencoded({ extended: true }))
app.use(bodyParser.json())
app.post('/getUserByPhone',(request,response)=>{
MongoDB.connectDB(async (err) => {
assert.equal(null, err);
console.log("Connected correctly to server");
const db = MongoDB.getDB();
const collection = db.collection('users');
console.log(request.body.phone);
// Find some documents
collection.find({/*Query here*/}).toArray(function(err, docs) {
assert.equal(err, null);
console.log("Found the following records");
console.log(docs)
response.send(docs);
})
})
})
app.post('/getUserById',(request,response)=>{
var ObjectId = require('mongodb').ObjectId;
var id = request.body.userId;
var userId = new ObjectId(id);
MongoDB.connectDB(async (err) => {
assert.equal(null, err);
const db = MongoDB.getDB();
console.log("Connected correctly to server");
const collection = db.collection('users');
collection.find({/*Query*/}).toArray(function(err, docs) {
assert.equal(err, null);
console.log("Found the following records");
console.log(docs)
response.send(docs);
})
})
})
app.post('/moreFunction',async(request,response)=>{
var currTime = new Date();
MongoDB.connectDB(async (err) => {
assert.equal(null, err);
const db = MongoDB.getDB();
const collection = db.collection('coll_2');
collection.find().toArray(function(err, docs) {
assert.equal(err, null);
response.send(docs);
});
})
})
app.post('/anotherFunction',async(request,response)=>{
MongoDB.connectDB(async (err) => {
assert.equal(null, err);
const db = MongoDB.getDB();
console.log("Connected correctly to server");
const collection = db.collection('coll_name');
collection.find().toArray(function(err, docs) {
assert.equal(err, null);
response.send(docs);
});
})
})
exports.api = functions.https.onRequest(app);
现在,每当我通过在我的 Android 设备上运行我的应用程序来测试它时,我都会在我的 MongoDb 控制台中看到连接高峰。当我在屏幕之间导航时,我看到应用程序使用了大约 25-30 个连接,而不是一个连接。我的方法有什么问题?为什么要使用这么多连接?
此应用未发布,我是唯一用户。
【问题讨论】:
-
我相信您在这里使用 connectDB() --> 对于基本上创建新连接的每个请求,而不是重用连接。
-
这就是本文推荐的内容:stackoverflow.com/questions/24621940/…。它说“这样做的原因是,在节点中,当模块被要求时,它们只会被加载/获取一次,所以你只会得到一个 _db 实例,而 mongoUtil.getDb() 将始终返回同一个实例。”
-
只在应用程序级别连接到数据库一次,并在路由级别使用该连接。现在,在每条路线上,您都在建立新的连接。
-
@VikalpJain 但您没有在每个请求上调用 MongoDB.connectDB(async (err)) ,因此始终会创建新连接。您应该在 mongoUtil 类初始化中只连接一次 DB。在每个请求中,您应该只使用 MongoDB.getDB()
-
感谢@Lucia 和 Sandor Bakos。我现在明白我犯的错误了。为了克服我尝试将我的 getDB 函数更改为: const getDB = async() => { try{ if (!_db){await connectDB()} return _db } catch (e) { throw e } } 而不是 ConnectDB,现在我从我的路由函数中调用 getDB。但这给出了“回调不是函数”错误。
标签: node.js mongodb firebase express google-cloud-functions