如何限制 imagemin-mozjpeg 中子进程的数量?
How can I limit the number of child processes in imagemin-mozjpeg?
我正在使用 imagemin-mozjpeg,它使用 mozjpeg 二进制文件来压缩图像。
问题是我在 nodejs 网络服务器中使用它。
现在是这样的:
我正在使用 "request" 模块 (fs.createReadStream) 上传 JPEG 图片。
Multer对流进行处理并保存在缓冲区(内存存储)中。
然后将buffer传给imagemin进行压缩
然后将压缩缓冲区写入文件。 (example.jpg)
一切正常。
这里的问题是,对于每个请求,都会产生一个新的 mozjpeg 二进制子进程 cjpeg。
1 个子进程消耗 12.5 MB 内存(对于 .5 MB 文件)。
如果我同时有 50 个请求,那将达到 ~700 MB,因为对于 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()
(生成图像处理进程)的调用次数。
也许你可以实现一个任务调度系统,使用任务队列来收集请求,并使用一些 worker 来处理请求 imagemin()
。
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])
}
})
请注意,由于您的调度程序是从 Array
扩展而来的,您可以使用任何 Array
方法来管理您的任务,例如pop()
丢弃最后一个任务,shift()
丢弃第一个任务,unshift(newTask)
在调度程序队列的开头插入一个新任务。
我正在使用 imagemin-mozjpeg,它使用 mozjpeg 二进制文件来压缩图像。
问题是我在 nodejs 网络服务器中使用它。
现在是这样的:
我正在使用 "request" 模块 (fs.createReadStream) 上传 JPEG 图片。
Multer对流进行处理并保存在缓冲区(内存存储)中。
然后将buffer传给imagemin进行压缩
然后将压缩缓冲区写入文件。 (example.jpg)
一切正常。
这里的问题是,对于每个请求,都会产生一个新的 mozjpeg 二进制子进程 cjpeg。
1 个子进程消耗 12.5 MB 内存(对于 .5 MB 文件)。
如果我同时有 50 个请求,那将达到 ~700 MB,因为对于 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()
(生成图像处理进程)的调用次数。
也许你可以实现一个任务调度系统,使用任务队列来收集请求,并使用一些 worker 来处理请求 imagemin()
。
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])
}
})
请注意,由于您的调度程序是从 Array
扩展而来的,您可以使用任何 Array
方法来管理您的任务,例如pop()
丢弃最后一个任务,shift()
丢弃第一个任务,unshift(newTask)
在调度程序队列的开头插入一个新任务。