safeify icon indicating copy to clipboard operation
safeify copied to clipboard

直接并发执行多个异步函数时,会串行消费

Open LincWong opened this issue 6 years ago • 2 comments

例子

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)

最好还是优化这个队列消费逻辑

LincWong avatar Dec 17 '19 07:12 LincWong

@Houfeng

LincWong avatar Dec 17 '19 07:12 LincWong

我确认并处理一下

Houfeng avatar Feb 15 '20 01:02 Houfeng