You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Express服务器无法异步处理并发API请求(需等待旧请求完成)

MEVN栈后端请求阻塞问题排查

问题概述

我基于MEVN栈(MongoDB、Express、VueJS、Node)开发首个Web应用,按预期Node.js的请求处理应该是异步非阻塞的,但实际所有请求都会被阻塞,必须等前一个请求处理完成才能响应下一个。比如用户通过POST上传数据时,其他用户的GET请求会完全挂起,直到POST操作结束。

测试验证

我做了如下测试:

  • 访问服务器的/test路由(该路由包含5秒延迟)
  • 同时用Postman调用/api路由
    结果Postman的请求会一直挂起,直到/test路由的延迟结束后才会得到响应。

相关代码片段

server.js头部代码

// Importing required modules
const bodyParser = require('body-parser');
const cors = require('cors');
const express = require('express');
const morgan = require('morgan');
const multer = require('multer');
const hashlips = require('./src/main.js')
const fs = require('fs-extra');

// parse env variables
require('dotenv').config();

require("./helpers/db/mongodb.js")();

// Configuring port
const port = process.env.PORT || 9000;

//configure express
const app = express();

// Configure middlewares
app.use(cors());
app.use(express.json({ limit: '10mb' }));
app.use(morgan('dev'));
app.use(bodyParser.json({ limit: '10mb' }));
app.use(express.urlencoded({extended: true}, { limit: '10mb' }));
app.set('view engine', 'html');

// Static folder
app.use(express.static(__dirname + '/views/'));

// Defining route middleware
app.use('/api', require('./routes/api'));

//routes
app.get('/test', (req, res) => {
    await new Promise(r => setTimeout(r, 5000));
    res.send("<h3>Express Server")
})

api.js路由代码

const express = require('express');

const {
  //init CRUD
  createData,
  readData,
  updateData,
  deleteData,
  deleteAllData,
  //init register login
  registerNewUser,
  loginUser,
  getUserDetails,
  //init collection saving
  createCollection,
  readCollectionData,
  deleteAllCollections,
  deleteCollection,
  updateCollection,
} = require('../controllers/user_controller');

const auth = require('../config/auth')

const router = express.Router();

router
  .put("/collection", createCollection)
  .put("/collectionu", updateCollection)
  .post("/", createData)
  .post("/register", registerNewUser)
  .post("/login", loginUser)
  .get("/collection", readCollectionData)
  .get("/me", auth, getUserDetails)
  .get('/', readData)
  .put('/:id', updateData)
  .delete('/deletecollections', deleteAllCollections)
  .delete('/deleteall', deleteAllData)
  .delete('/deletecollection/:id', auth, deleteCollection)
  .delete('/:id', deleteData);

module.exports = router;

同步API警告堆栈跟踪

启动时添加--trace-sync-io参数得到以下堆栈信息:

(node:62551) WARNING: Detected use of sync API
    at pbkdf2Sync (node:internal/crypto/pbkdf2:80:37)
    at HI (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/cmap/auth/scram.js:245:31)
    at continueScramConversation (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/cmap/auth/scram.js:138:28)
    at /home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/cmap/auth/scram.js:90:9
    at onMessage (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/cmap/connection.js:222:9)
    at /home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/cmap/connection.js:63:60
    at emit (node:events:394:28)
    at processIncomingData (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/cmap/message_stream.js:132:20)
    at _write (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/cmap/message_stream.js:33:9)
    at writeOrBuffer (node:internal/streams/writable:389:12)
Connected to MongoDB
(node:62551) WARNING: Detected use of sync API
    at randomFillSync (node:internal/crypto/random:137:19)
    at randomBytes (node:internal/crypto/random:99:5)
    at uuidV4 (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/utils.js:439:27)
    at ServerSession (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/sessions.js:541:62)
    at acquire (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/sessions.js:619:16)
    at get serverSession (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/sessions.js:94:46)
    at applySession (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/sessions.js:670:35)
    at command (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/cmap/connection.js:278:53)
    at /home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/sdam/server.js:210:18
    at /home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/cmap/connection_pool.js:271:13
(node:62551) WARNING: Detected use of sync API
    at randomFillSync (node:internal/crypto/random:137:19)
    at randomBytes (node:internal/crypto/random:99:5)
    at ObjectId.generate (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/bson/lib/objectid.js:145:54)
    at ObjectId (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/bson/lib/objectid.js:47:34)
    at NativeCollection.<computed> (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js:84:18)
    at create (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongoose/lib/model.js:1803:22)
    at /home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongoose/lib/model.js:1764:7
    at processTicksAndRejections (node:internal/process/task_queues:78:11)

问题分析与解决建议

核心原因

Node.js是单线程事件循环模型,一旦出现同步阻塞API调用,会直接卡住整个事件循环,导致所有后续请求无法被处理。从堆栈跟踪可以看到,MongoDB驱动底层使用了多个同步API:

  • pbkdf2Sync:SCRAM认证时的同步密钥派生
  • randomFillSync:生成UUID和ObjectId时的同步随机数生成

这些同步操作是导致请求阻塞的根本原因。另外你的/test路由代码存在语法错误:回调函数没有声明为async就使用await,会直接抛出异常,也可能影响测试结果。

解决步骤

  1. 修复/test路由语法错误
    给路由回调添加async关键字,确保异步延迟不会阻塞:

    app.get('/test', async (req, res) => {
        await new Promise(r => setTimeout(r, 5000));
        res.send("<h3>Express Server</h3>")
    })
    

    这个路由本身是异步非阻塞的,修复后可以单独验证Node.js的异步处理能力。

  2. 升级MongoDB驱动与Mongoose
    旧版本的MongoDB驱动可能存在同步阻塞调用,升级到最新稳定版可以避免这类问题:

    npm install mongodb@latest mongoose@latest
    
  3. 确保MongoDB连接使用异步方式
    检查helpers/db/mongodb.js,改用异步连接:

    const mongoose = require('mongoose');
    module.exports = async () => {
        try {
            await mongoose.connect(process.env.MONGODB_URI);
            console.log('Connected to MongoDB');
        } catch (error) {
            console.error('MongoDB connection failed:', error);
        }
    };
    
  4. 避免所有同步API调用
    检查代码中是否使用了其他Sync后缀的API(比如fs.readFileSync),全部替换为异步版本(比如fs.promises.readFile)。

内容的提问来源于stack exchange,提问作者Zach Hopkins

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 08:06:18