5

在 Nodejs 中,使用 Express 作为服务器,我将繁重的计算卸载到工作线程上。

在主应用程序中,我这样调用工作线程:

// file: main.js

const { Worker } = require("worker_threads");

function runService(fileName, workerData) {
    return new Promise((resolve, reject) => {
        const worker = new Worker(fileName, { workerData });
        worker.on("message", resolve);
        worker.on("error", reject);
        worker.on("exit", code => {
            if (code !== 0)
                reject(new Error(`Worker stopped with exit code ${code}`));
        });
    });
}

router.get("/some_url", async function(req, res) {
    const result = await runService(
        "./path/to/worker.js",
        { query: req.query, user: req.user } // using { req } causes an error
    );
});

工人看起来像这样:

// file: worker.js

const { workerData, parentPort } = require('worker_threads');
const { query, user } = workerData;

async function run() {
    const result = await generateLotsOfData(query, user);

    parentPort.postMessage(result);

    // What I would like to do here (doesn't work): res.send(result);
}

工作人员生成大量数据,“postMessage”导致服务器错误。

有没有办法将这些数据从工作线程直接发送到客户端,使用res.send()或类似的东西?
(而不是使用postMessage然后从主线程发送)?

4

1 回答 1

0

似乎不可能直接从工人踏板发送到客户端。
最后,我使用了子进程(而不是工作线程),并将结果发送回主线程,然后发送给客户端。

// file: main.js

var child_process = require('child_process');

// Run a worker thread
function runService(fileName, workerData) {
    return new Promise((resolve, reject) => {

        const worker = child_process.fork(fileName);

        worker.on('message', function(message) {
            if (message.ready) {
                // worker is ready to receive data
                worker.send(workerData);
            } else {
                // worker finished it's calculations, send the data to the client
                resolve(message);
            }
        });

        worker.on("error", function(x) {
            console.log('error', x);
            resolve({status: 500});
        });
        worker.on("close", function(y) {
            console.log('close', y);
        });
        worker.on("exit", function(code) {
            if (code == 0) {
                console.log('report ran successfully');
            } else {
                console.log('report FAILED');
                resolve({status: 500});
            }
        });
    });
}

在工人中:

process.on('message', run);
process.send({ready: true});

async function run(workerData) {
    try {
        const result = doSomeCalculations();

        process.send({
            data: JSON.stringify(result)
        }, null, {}, function() {process.exit(0)});
    } catch(err) {
        console.error(err);
        process.exit(1); // exit the process with a failure
    }
}

// Make sure that this child_process doesn't accidentally stay in memory.
// Kill after 10 minutes. (not sure this is necessary, just to be sure)
setTimeout(function(){
    console.log('Timeout in child-process');
    process.exit(1);
}, 600000);

这实际上工作得很好。

于 2020-01-02T10:50:41.793 回答