Node.js 如何限制imagemin mozjpeg中的子进程数?

Node.js 如何限制imagemin mozjpeg中的子进程数?,node.js,compression,imagemin,mozjpeg,Node.js,Compression,Imagemin,Mozjpeg,我正在使用imagemin mozjpeg,它使用mozjpeg二进制文件来压缩图像 问题是我正在nodejs Web服务器中使用它 这就是它现在的工作原理: 我正在使用“请求”模块(fs.createReadStream)上传JPEG图像 Multer处理流并将其保存在缓冲区(内存存储)中 然后将缓冲区传递给imagemin进行压缩 然后将压缩的缓冲区写入文件。(example.jpg) 一切正常 这里的问题是,对于每个请求,都会产生一个新的mozjpeg二进制子进程cjpeg 1个子进程占用

我正在使用imagemin mozjpeg,它使用mozjpeg二进制文件来压缩图像

问题是我正在nodejs Web服务器中使用它

这就是它现在的工作原理:

  • 我正在使用“请求”模块(fs.createReadStream)上传JPEG图像

  • Multer处理流并将其保存在缓冲区(内存存储)中

  • 然后将缓冲区传递给imagemin进行压缩

  • 然后将压缩的缓冲区写入文件。(example.jpg)

  • 一切正常

    这里的问题是,对于每个请求,都会产生一个新的mozjpeg二进制子进程cjpeg

    1个子进程占用12.5 MB内存(对于.5 MB文件)

    如果我同时有50个请求,那么会达到700MB,因为对于50个图像,有50个子进程

    有没有办法限制子进程的数量?(库正在使用“execa”模块)或只生成4-5个子进程,它们对所有请求进行压缩

    谢谢

    if (req.files.myimage[0].buffer) {
                let fileNumber = filesUploaded++;
    
                imagemin.buffer(req.files.myimage[0].buffer, {
                    plugins: [
                        imageminMozjpeg({ quality: 60, progressive: true })
                    ]
                })
                    .then(file => {
                        fs.writeFile(__dirname + '/uploads/' + uuidv4() + '.jpg', file, 'hex' , function () {
                            res.end("SUCCESS" + fileNumber.toString());
                        });
    
                    })
                    .catch(err => {
                        console.log(err);
                        res.end("FAILED");
                    });
    
            }
    

    解决此问题的主要概念是限制对
    imagemin()
    (生成图像处理进程的人)的调用次数

    也许您可以实现一个任务调度系统,使用任务队列收集请求,并使用
    imagemin()
    处理请求

    var multer=require('multer'))
    var upload=multer({dest:'your/uploads/'})
    //TaskScheduler,任务数组的包装器
    类TaskScheduler扩展了数组{
    构造器(最大槽数,工人){
    超级()
    这个。_MAX_SLOTS=MAX_SLOTS
    这是。_busy_slots=0
    这是一个工人
    }
    /**
    *创建新任务
    */
    推送(…任务){
    const ret=super.push(…任务)
    this.run()
    回程网
    }
    /**
    *在可用插槽中运行任务
    */
    运行(){
    //如果有任何任务和可用插槽
    while(this.length>0&&this.\u busy\u slots{
    //释放插槽
    这是繁忙的插槽--
    //因为一个任务槽被释放了
    //再次调用run()以处理队列中的另一个任务
    this.run()
    })
    这是繁忙的插槽++
    }
    }
    }
    //工人应该兑现诺言
    常量调度程序=新任务调度程序(5,函数(任务){
    返回imagemin.buffer(task.buffer,{/*imagemin选项*/})
    。然后(()=>{/*写入图像文件*/})
    .catch(()=>{/*错误处理*/})
    })
    //在有传入请求时安排任务
    //实际代码取决于您的web服务器
    //这里,回调中要做的就是重点;)
    //以express为例,`app`是express.Application
    app.post('your/end/point',upload.fields([{name:'myimage'}]),函数(req){
    if(req.files.myimage[0]){
    scheduler.push(req.files.myimage[0])
    }
    })
    

    请注意,由于您的计划程序是从
    Array
    扩展而来的,因此您可以使用任何
    Array
    方法来管理任务,例如
    pop()
    放弃最后一个任务,
    shift()
    放弃第一个任务和
    unshift(newTask)
    在调度程序队列的开头插入一个新任务。

    感谢您的建议。现在我要试着做实验。:)req.files是一个空对象。有什么想法吗?我认为这是因为它还没有通过multer。然后在multer中间件之后注册您的任务调度程序中间件。如果您使用的是express,express Middleware将按照调用
    express.use()
    的顺序执行。我已将代码更新为包含
    express
    multer
    。试试看是否有问题;)
        var multer  = require('multer')
        var upload = multer({ dest: 'your/uploads/' })
    
        // TaskScheduler, a wrapper of a task array
        class TaskScheduler extends Array {
          constructor (MAX_SLOTS, worker) {
            super()
            this._MAX_SLOTS= MAX_SLOTS
            this._busy_slots= 0
            this._worker= worker
          }
    
          /**
           * Create new tasks
           */
          push (...tasks) {
            const ret = super.push(...tasks)
    
            this.run()
            return ret
          }
    
          /**
           * Run tasks in available slots
           */
          run () {
            // if there are any tasks and available slots
            while (this.length > 0 && this._busy_slots < this._MAX_SLOTS) {
              const firstTask = this.shift()
              this._worker(firstTask).then(() => {
                // release the slot
                this._busy_slots--
    
                // since a task slot is released
                // call run() again to process another task from the queue
                this.run()
              })
              this._busy_slots++
            }
          }
        }
    
        // worker is supposed to return a Promise
        const scheduler = new TaskScheduler(5, function (task) {
          return imagemin.buffer(task.buffer, { /* imagemin options */ })
            .then(() => { /* write image files */ })
            .catch(() => { /* error handling */ })
        })
    
        // schedule the task when there is an incoming request
        // the actual code depends on your web server
        // here what to do in the callback is the point ;)
    
        // Take express for example, `app` is the express.Application
        app.post('your/end/point', upload.fields([{ name: 'myimage' }]), function (req) {
          if (req.files.myimage[0]) {
            scheduler.push(req.files.myimage[0])
          }
        })