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
相关产品推荐
相关产品推荐

