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

如何让Express Node.js应用在处理长请求时支持多用户并行运行?

解决Express长请求处理期间的并发访问问题

嘿,这个问题的核心是要让你的Express应用在处理长耗时请求时,不会阻塞其他用户的请求。其实Node.js的事件循环本身就支持异步并发,再配合PM2的集群模式和Nginx的反向代理配置,就能完美解决这个问题。我来一步步给你拆解实现方案:

1. 先确保你的请求处理流程完全异步(别阻塞事件循环)

Node.js是单线程事件循环模型,只要所有IO操作(API请求、文件读写)都是异步的,就不会阻塞其他请求的处理。你要避免使用任何同步方法(比如fs.appendFileSync),否则会卡住整个事件循环,导致后续请求排队等待。

这里给你一个符合要求的Express路由示例,处理CSV上传、并发API请求、异步文件写入:

const express = require('express');
const multer = require('multer'); // 处理文件上传
const fs = require('fs').promises; // 用Promise版的fs模块
const { v4: uuidv4 } = require('uuid'); // 生成唯一文件名
const axios = require('axios');
const pLimit = require('p-limit'); // 控制API并发数,避免触发接口限流

const app = express();
const upload = multer({ dest: './temp-uploads/' }); // 临时存储上传的CSV
const apiConcurrencyLimit = pLimit(10); // 限制同时发起10个API请求,可根据接口调整

// 处理CSV的核心接口
app.post('/process-csv', upload.single('csv'), async (req, res) => {
  try {
    // 1. 生成唯一输出文件名,避免多个请求写入同一个文件导致冲突
    const outputFilePath = `./processed-files/${uuidv4()}-results.txt`;
    await fs.writeFile(outputFilePath, ''); // 创建空文件

    // 2. 读取并解析CSV文件(实际项目建议用csv-parser库处理,这里简化为按行分割)
    const csvContent = await fs.readFile(req.file.path, 'utf8');
    const dataRows = csvContent.split('\n').filter(row => row.trim() !== '');
    const totalRows = dataRows.length;

    // 3. 用p-limit控制并发API请求,避免一次性发起太多请求被封禁
    const apiTasks = dataRows.map(row => apiConcurrencyLimit(async () => {
      // 发起异步API请求
      const apiResponse = await axios.get(`https://your-target-api.com/data?param=${encodeURIComponent(row)}`);
      // 异步追加写入结果到文件,不会阻塞事件循环
      await fs.appendFile(outputFilePath, `${JSON.stringify(apiResponse.data)}\n`);
    }));

    // 4. 等待所有并发API任务完成
    await Promise.all(apiTasks);

    // 5. 进一步处理结果文件(比如汇总、转换格式等)
    const finalResult = await fs.readFile(outputFilePath, 'utf8');
    // ... 这里添加你的后续处理逻辑 ...

    // 6. 返回响应给前端
    res.status(200).json({
      success: true,
      message: `处理完成,共处理${totalRows}条数据`,
      result: finalResult
    });

    // 7. 清理临时文件(上传的CSV和处理后的结果文件,根据需求保留)
    await fs.unlink(req.file.path);
    await fs.unlink(outputFilePath);
  } catch (error) {
    console.error('请求处理出错:', error);
    res.status(500).json({ success: false, error: '处理失败,请稍后重试' });
  }
});

app.listen(4000, () => {
  console.log('Express应用运行在端口4000');
});

2. 用PM2集群模式提升并发能力

虽然Node.js的异步模型能处理多个请求,但单进程的并发能力有限。PM2的集群模式可以启动多个Node.js进程,充分利用服务器的多核CPU,每个进程独立处理请求队列。这样即使某个进程正在处理一个5分钟的长请求,其他进程依然能接收并处理新用户的请求。

配置PM2集群模式

创建一个ecosystem.config.js配置文件:

module.exports = {
  apps: [{
    name: 'your-express-app', // 应用名称
    script: './app.js', // 入口文件
    instances: 'max', // 启动与CPU核心数相同的进程数
    exec_mode: 'cluster', // 启用集群模式
    env: {
      NODE_ENV: 'production'
    },
    log_date_format: 'YYYY-MM-DD HH:mm:ss', // 日志时间格式
    combine_logs: true, // 合并所有进程的日志
    max_memory_restart: '500M' // 进程内存超过500M时自动重启,防止内存泄漏
  }]
};

启动PM2

运行以下命令启动应用:

pm2 start ecosystem.config.js

3. Nginx反向代理的关键配置

Nginx作为前端和Express应用之间的反向代理,需要注意两个核心配置:

  • 负载均衡:把请求分发给PM2的多个集群进程
  • 超时时间:默认Nginx会在60秒后断开未响应的请求,而你的请求需要5分钟,必须延长超时时间

Nginx配置示例

server {
    listen 80;
    server_name your-domain.com; # 替换为你的域名

    location / {
        proxy_pass http://localhost:4000; # 代理到Express应用的端口
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;

        # 设置超时时间为6分钟(360秒),比你的处理时间长一点
        proxy_connect_timeout 360s;
        proxy_send_timeout 360s;
        proxy_read_timeout 360s;
    }
}

配置完成后,重启Nginx使配置生效:

sudo nginx -s reload

4. 额外优化建议

  • 添加进度反馈:对于5分钟的长请求,前端用户可能会以为请求卡住了。可以用**Server-Sent Events(SSE)**或WebSocket实时返回处理进度,提升用户体验。
  • 错误隔离:在async函数中用try/catch捕获所有错误,避免单个请求的错误导致整个进程崩溃。
  • 文件清理机制:定时清理临时文件夹中的未处理文件,防止磁盘空间被占满。
  • API请求重试:给异步API请求添加重试逻辑(比如用axios-retry),提升容错性。

按照以上步骤配置后,你的Express应用就能在处理长耗时请求的同时,正常响应其他用户的请求了。

内容的提问来源于stack exchange,提问作者Álvaro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 10:27:39