【问题标题】:Write to excel on http post request in a non-blocking way以非阻塞方式在 http post 请求上写入 excel
【发布时间】:2021-05-10 15:29:53
【问题描述】:

我的 Web 服务器上有一个端点,用于处理具有包含对 mongodb 数据库查询的正文的发布请求。然后使用 exceljs 一次一个文档将查询结果写入一个 excel 文件。当查询产生合理数量的文档时,它一旦准备好就可以很好地响应文件名。当查询来自多个请求的 200k+ 个文档时,就会出现问题。发生的情况是,通常需要大约 1 分钟才能完成编写和响应单个客户端请求 500k+ 个文档,而完成编写和响应多个请求并查询相同数量的文档甚至更少需要几分钟。

端点几乎是这样的:

app.post('/queryToExcel', async (req, res) => {
    let cursor = mongodb.collection('collection').find(req.body);
    let filename = `./files/excel${Date.now()}`;
    let workbook = new Excel.stream.xlsx.WorkbookWriter({ filename: filename });
    let worksheet = workbook.addWorksheet("Sheet 1");

    let isFirstDoc = true;
    await cursor.forEach(document => {
        if (isFirstDoc) {
            worksheet.columns = getColumnNames(document);
            isFirstDoc = false;
        }
        worksheet.addRow(row).commit();
    });
    
    await workbook.commit();

    res.send(filename);
});

无论网络服务器是否正在处理对其他文件的其他请求,我应该如何在与查询请求的文档数量相关的时间范围内做出响应?是线程问题还是我做错了什么?

【问题讨论】:

    标签: node.js mongodb exceljs


    【解决方案1】:

    如果您使用的库不公开 Async API,那么我建议您使用工作线程,否则您只有一个线程。

    要以最有效的方式使用工作人员,我建议您使用 queue lib BullMQ

    【讨论】:

      【解决方案2】:

      我通过在每个请求上创建一个分叉的子进程来解决,如下所示:

      端点:

      const { fork } = require('child_process');
      
      app.post('/queryToExcel', async (req, res) => {
          const childProcess = fork("./writer.js");
          childProcess.send(req.body);
          childProcess.on('message', filename => {
              res.send(filename);
              childProcess.kill();
          });
      });
      

      子进程执行的文件writer.js

      const writer = (reqBody) => {
          let cursor = mongodb.collection('collection').find(ReqBody);
          let filename = `./files/excel${Date.now()}`;
          let workbook = new Excel.stream.xlsx.WorkbookWriter({ filename: filename });
          let worksheet = workbook.addWorksheet("Sheet 1");
          let isFirstDoc = true;
          await cursor.forEach(document => {
              if (isFirstDoc) {
                  worksheet.columns = getColumnNames(document);
                  isFirstDoc = false;
              }
              worksheet.addRow(row).commit();
          });
          
          await workbook.commit();
      
          process.send(filename);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-19
        • 1970-01-01
        相关资源
        最近更新 更多