Node.js 接口响应太慢,怎么优化性能?

闲人统泽 阅读 2

我用 Node.js 写了个 API 接口,前端用 Vue 调用,但每次加载都要等好几秒,本地开发都卡。试过加缓存和减少数据库查询,还是没明显改善。

前端是这样调用的:

<template>
  <div v-if="loading">加载中...</div>
  <ul v-else>
    <li v-for="item in items" :key="item.id">{{ item.name }}</li>
  </ul>
</template>

<script>
export default {
  data() { return { items: [], loading: true } },
  async mounted() {
    const res = await fetch('/api/data');
    this.items = await res.json();
    this.loading = false;
  }
}
</script>

后端就是普通的 Express 路由,查 MongoDB 返回数据。有没有什么靠谱的优化方向?比如流式响应、集群部署,或者我代码哪里写得有问题?

我来解答 赞 0 收藏
二维码
手机扫码查看
1 条解答
FSD-昊沅
这个问题挺常见的,我帮你理一理思路。几秒钟肯定不正常,咱们一步步排查。

先说几个最可能的原因:

1. MongoDB 查询没有索引

这个是大多数人忽略的。你想啊,如果你的数据量稍微大一点,每次查询都要全表扫描,那肯定慢。比如你按 name 查,就应该在 name 字段上加索引:

// 在 MongoDB 里这样创建索引,或者在 Mongoose 模型里定义
db.collection.createIndex({ name: 1 });
// 或者 Mongoose 写法
UserSchema.index({ name: 1 });


2. 返回了太多不必要的字段

很多人写查询是这样的:

// 假设 User 表有 20 个字段,但你只需要 name 和 id
const users = await User.find(); // 查全部字段


改成这样:

// 只查需要的字段,projection 减少数据传输量
const users = await User.find({}, { name: 1, _id: 1 });
// 或者 Mongoose 写法
const users = await User.find().select('name _id');


3. N+1 查询问题

如果你查询的是关联数据,比如每个用户有个 posts 数组,然后你又循环查了一遍:

// 错误写法 - N+1 问题
const users = await User.find();
for (const user of users) {
const posts = await Post.find({ userId: user._id }); // 每个用户都查一次
}


改成用 populate 或者聚合查询一次查出来:

// 正确写法 - 一步到位
const users = await User.find().populate('posts');
// 或者用聚合
const users = await User.aggregate([
{
$lookup: {
from: 'posts',
localField: '_id',
foreignField: 'userId',
as: 'posts'
}
}
]);


4. MongoDB 连接池没配好

Express 默认的 MongoDB 连接可能没配连接池,高并发或者数据量大的时候就会卡:

// 改成这样配连接池
mongoose.connect('mongodb://localhost/myapp', {
poolSize: 10, // 连接池大小,默认 5,可以调大点
socketTimeoutMS: 45000,
serverSelectionTimeoutMS: 5000
});


5. 看一下你的后端代码大概长什么样

你可以先在接口里加点日志,看看是哪部分慢:

router.get('/data', async (req, res) => {
console.time('total');

console.time('db-query');
const data = await Model.find();
console.timeEnd('db-query');

console.time('process');
// 这里是处理数据的逻辑
const result = data.map(item => ({
id: item._id,
name: item.name
}));
console.timeEnd('process');

console.time('response');
res.json(result);
console.timeEnd('response');

console.timeEnd('total');
});


运行一下,看控制台哪个 time 最长,就知道瓶颈在哪了。

关于你提到的流式响应

流式响应其实不太适合 JSON API,因为你要返回完整的 JSON 结构,必须等数据全部准备好才能开始发送。流式更适合大文件下载那种场景。对于普通接口,优化数据库查询才是正路。

关于集群部署

这是最后的手段,而且前提是你把单机优化做到位了。如果单线程都慢,集群只会让问题更明显。先把上面几个检查一遍。

你现在可以在后端接口里加上 console.time 看看哪个环节慢,定位到问题再针对性解决。
点赞
2026-03-13 20:10