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

Node.js证书生成模块:多并行请求下同步串行处理及独立子进程实现方案咨询

问题:Node.js证书生成模块的并行请求串行处理与进程隔离需求

我正在用Node.js构建一个证书生成模块,当前的API代码如下:

// Create certificate
const express = require('express');
const router = express.Router();
const { createCanvas } = require('canvas')
const fs = require("fs");
const { decodeBase64Image } = require('../helper/certificatehelper');

router.post('/imageadd', async (req, res, next) => {
  try {
    const { name } = req.body;
    const width = 1920
    const height = 1080
    const canvas = createCanvas(width, height)
    const context = canvas.getContext('2d')
    context.fillStyle = "white";
    context.fillRect(0, 0, width, height)
    context.fillStyle = '#000'
    context.font = "72px Arial";
    context.textAlign = "center";
    context.fillText(name, 900, 500);
    const dataurl = canvas.toDataURL();
    const decodedImg = decodeBase64Image(dataurl);
    const imageBuffer = decodedImg.data;
    fs.writeFileSync(`./src/images/image1.png`, imageBuffer);
    fs.readFile('./src/images/image1.png', function(err, data) {
      if (err) throw err; // Fail if the file can't be read.
      res.writeHead(200, {'Content-Type': 'image/jpeg'});
      res.end(data); // Send the file data to the browser.
    });
    res.json({ data: respArray, success: true, msg: 'Certificate generated' });
  } catch (error) {
    res.json({ success: false, msg: error.message });
  }
})

module.exports = router;

现在遇到两个核心问题:

  • 当多个请求并行发送时,需要实现证书的同步串行生成(即每个证书生成完成后再处理下一个请求,其他请求需等待前一个完成)
  • 证书生成操作需要在主应用进程之外的独立进程中执行,避免阻塞主进程

请问该如何解决这两个问题?


解决方案

1. 串行处理请求:用Promise队列控制执行顺序

首先我们需要一个队列来管理所有证书生成请求,确保同一时间只有一个任务在执行。不需要额外安装依赖,自己就能实现一个简易的Promise队列:

const express = require('express');
const router = express.Router();
const { fork } = require('child_process');
const path = require('path');

// 初始化一个空的Promise队列,用于串行处理请求
let taskQueue = Promise.resolve();

// 封装队列添加函数,确保任务按顺序执行
function addToQueue(task) {
  taskQueue = taskQueue.then(task).catch(err => console.error('队列任务执行失败:', err));
  return taskQueue;
}

router.post('/imageadd', async (req, res, next) => {
  try {
    const { name } = req.body;

    // 将当前请求的处理逻辑加入串行队列
    await addToQueue(() => new Promise((resolve, reject) => {
      // 启动独立子进程执行证书生成任务
      const certProcess = fork(path.join(__dirname, './certificate-generator.js'));
      
      // 向子进程传递生成证书所需的参数
      certProcess.send({ name });

      // 监听子进程返回的结果
      certProcess.on('message', (result) => {
        if (result.success) {
          // 直接返回生成的图片Buffer给客户端
          res.writeHead(200, {'Content-Type': 'image/png'});
          res.end(result.imageBuffer);
          resolve();
        } else {
          res.status(500).json({ success: false, msg: result.error });
          reject(new Error(result.error));
        }
      });

      // 监听子进程错误
      certProcess.on('error', (err) => {
        res.status(500).json({ success: false, msg: err.message });
        reject(err);
      });

      // 监听子进程异常退出
      certProcess.on('exit', (code) => {
        if (code !== 0) {
          reject(new Error(`证书生成进程异常退出,退出码: ${code}`));
        }
      });
    }));
  } catch (error) {
    res.status(500).json({ success: false, msg: error.message });
  }
})

module.exports = router;

2. 独立进程执行生成逻辑:用child_process.fork创建子进程

把证书生成的核心逻辑抽离到单独的文件(比如certificate-generator.js),让它在独立进程中运行,避免阻塞主应用:

const { createCanvas } = require('canvas');
const { decodeBase64Image } = require('../helper/certificatehelper');

// 监听主进程发送的任务消息
process.on('message', async (data) => {
  try {
    const { name } = data;
    const width = 1920;
    const height = 1080;
    const canvas = createCanvas(width, height);
    const context = canvas.getContext('2d');

    // 绘制证书内容(修正了居中坐标,让文字更居中)
    context.fillStyle = "white";
    context.fillRect(0, 0, width, height);
    context.fillStyle = '#000';
    context.font = "72px Arial";
    context.textAlign = "center";
    context.fillText(name, width / 2, height / 2);

    // 直接生成图片Buffer,无需写入本地文件再读取,提升性能
    const dataUrl = canvas.toDataURL();
    const decodedImg = decodeBase64Image(dataUrl);
    const imageBuffer = decodedImg.data;

    // 将结果发送回主进程
    process.send({ success: true, imageBuffer });
    // 任务完成后主动退出子进程,避免资源泄漏
    process.exit(0);
  } catch (error) {
    // 发送错误信息回主进程
    process.send({ success: false, error: error.message });
    process.exit(1);
  }
});

额外优化说明

  • 移除了原代码中fs.writeFileSync+fs.readFile的冗余操作,直接用canvas生成的Buffer返回,减少IO开销
  • 子进程任务完成后主动调用process.exit(),避免闲置进程占用资源
  • 队列机制确保所有请求严格按顺序执行,不会出现并行生成导致的资源竞争或文件覆盖问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 04:49:05