MongoDB 从 Heroku 上的 Node.js 应用查询需要 2-3 秒

MongoDB queries are taking 2-3 seconds from Node.js app on Heroku

我在使用 MongoDB 时遇到了严重的性能问题。在少于 100 个文档的数据库中,简单的 find() 查询有时需要 2,000-3,000 毫秒才能完成。

我在 MongoDB Atlas M10 实例和我在具有 4GB RAM 的虚拟机上的 Digital Ocean 上设置的集群都看到了这一点。当我在 Heroku 上重新启动我的 Node.js 应用程序时,查询在 10-15 分钟内表现良好(少于 100 毫秒),但随后它们变慢了。

我是否错误地连接到 MongoDB 或从 Node.js 查询错误?请在下面查看我的应用程序代码。还是共享 VM 环境中硬件资源不足?

任何帮助将不胜感激。我已经完成了我知道如何使用 Explain 查询和 Mongo shell.

进行的所有故障排除
var Koa = require('koa'); //v2.4.1
var Router = require('koa-router'); //v7.3.0

var MongoClient = require('mongodb').MongoClient; //v3.1.3

var app = new Koa();
var router = new Router();

app.use(router.routes());

//Connect to MongoDB
async function connect() {
    try {
        var client = await MongoClient.connect(process.env.MONGODB_URI, {
            readConcern: { level: 'local' } 
        });
        var db = client.db(process.env.MONGODB_DATABASE);

        return db;
    }
    catch (error) {
        console.log(error);
    }
}

//Add MongoDB to Koa's ctx object
connect().then(db => {
    app.context.db = db;
});

//Get company's collection in MongoDB
router.get('/documents/:collection', async (ctx) => {
    try {
        var query = { company_id: ctx.state.session.company_id }; 

        var res = await ctx.db.collection(ctx.params.collection).find(query).toArray();

        ctx.body = { ok: true, docs: res };
    }
    catch (error) {
        ctx.status = 500;
        ctx.body = { ok: false };
    }
});

app.listen(process.env.PORT || 3000);

更新

我正在使用 MongoDB Change Streams 和标准服务器发送事件来为应用程序 UI 提供实时更新。我关闭了这些,现在 MongoDB 似乎再次表现良好。

MongoDB Change Streams 是否已知会影响 read/write 性能?

我建议你做更多的日志工作。重启一段时间后的慢查询可能比你想象的更糟。

对于普通机器上的现代 database/web 应用程序 运行,如果操作正确,则不太容易遇到性能问题。可能存在内存泄漏或其他未释放的资源,或网络拥塞。

恕我直言,您可能想先确定它是否是网络问题,然后通过在 MongoDB 上启用慢速查询登录并在查询开始和结束的代码中登录,您可以实现此目的。

如果网络完全正常并且您没有看到 MongoDB 缓慢的查询,则意味着您自己的应用程序出现问题。详细的日志记录可能真的有助于查询变慢的地方。

希望这会有所帮助。

Change Streams 确实会影响服务器的性能。如 中所述。

中所述,

The default connection pool size in the Node.js client for MongoDB is 5. Since each change stream cursor opens a new connection, the connection pool needs to be at least as large as the number of cursors.

const mongoConnection = await MongoClient.connect(URL, {poolSize: 100});

(Thanks to MongoDB Inc. for investigating this issue.)

您需要增加池大小才能恢复正常性能。