safeify
safeify copied to clipboard
直接并发执行多个异步函数时,会串行消费
例子
const { default: Safeify } = require('safeify');
(async () => {
const safeVm = new Safeify({
timeout: 5000, // 超时时间,默认 50ms
asyncTimeout: 5000, // 包含异步操作的超时时间,默认 500ms
workers: 4, // 沙箱进程数量
memoryQuota: 500, // 沙箱最大能使用的内存(单位 m),默认 500m
cpuQuota: 0.5, // 沙箱的 cpu 资源配额(百分比),默认 50%
})
// 定义 context
const insertEnv = {
event: {
},
context: {
a: async () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve('555555555')
}, 2000);
})
}
},
}
const fn2 = `
const res = await context.a()
return res `
const arr = [];
for (let i = 0; i < 10; i++) {
arr.push(safeVm.run(fn2, insertEnv));
}
const res = await Promise.all(arr);
console.log("TCL: serverless -> res", res)
})(undefined);
执行日志
safeify onWorkerDone result 47c13de4-9e5f-257c-355d-22cbec644f93 123123 +0ms
safeify this.options.greedy undefined +2ms
safeify execute pid 64465 +0ms
safeify worker.stats 1 +0ms
safeify execute code return 123123;
任务会一个一个执行,同时会一直分配同一个worker执行;
原因
在并发执行函数的时候,healthyWorkers堆栈为空,所以全部函数都push到执行队列去了;这时候消费队列逻辑里面,worker会一直分派给第一个worker; 具体代码:https://github.com/Houfeng/safeify/blob/master/src/Safeify.ts#L248
const worker = this.options.greedy === false
? this.healthyWorkers.find(w => w.stats < 1)
: this.healthyWorkers.sort((a, b) => a.stats - b.stats)[0];
解决
临时解决方案:在执行并发函数之前,执行一个预热函数,让worker全部处于健康状态; 当实际需要的时候再使用就可以并发执行了。
const pre = await safeVm.run(fn2, insertEnv)
console.log("TCL: pre", pre)
最好还是优化这个队列消费逻辑
@Houfeng
我确认并处理一下